1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2021 Intel Corporation. All rights reserved.
4  */
5 
6 /*
7  * Some of the structures may contain programming implementations that makes them
8  * unsuitable for generic use and general usage.
9  *
10  * This code is mostly copied "as-is" from existing C++ interface files hence the use of
11  * different style in places. The intention is to keep the interface as close as possible to
12  * original so it's easier to track changes with IPC host code.
13  */
14 
15 /**
16  * \file include/ipc4/module.h
17  * \brief IPC4 module definitions
18  * NOTE: This ABI uses bit fields and is non portable.
19  */
20 
21 #ifndef __IPC4_MODULE_H__
22 #define __IPC4_MODULE_H__
23 
24 #include <ipc4/error_status.h>
25 
26 #include <stdint.h>
27 
28 /* TODO: revisit it. Now it aligns with audio sdk
29  * and we will update this value and sdk when more
30  * libraries are supported
31  */
32 #define IPC4_MAX_SUPPORTED_LIBRARIES 16
33 
34 #define IPC4_MAX_MODULE_COUNT 128
35 
36 #define SOF_IPC4_DST_QUEUE_ID_BITFIELD_SIZE	3
37 #define SOF_IPC4_SRC_QUEUE_ID_BITFIELD_SIZE	3
38 
39 enum sof_ipc4_module_type {
40 	SOF_IPC4_MOD_INIT_INSTANCE		= 0,
41 	SOF_IPC4_MOD_CONFIG_GET			= 1,
42 	SOF_IPC4_MOD_CONFIG_SET			= 2,
43 	SOF_IPC4_MOD_LARGE_CONFIG_GET		= 3,
44 	SOF_IPC4_MOD_LARGE_CONFIG_SET		= 4,
45 	SOF_IPC4_MOD_BIND			= 5,
46 	SOF_IPC4_MOD_UNBIND			= 6,
47 	SOF_IPC4_MOD_SET_DX			= 7,
48 	SOF_IPC4_MOD_SET_D0IX			= 8,
49 	SOF_IPC4_MOD_ENTER_MODULE_RESTORE	= 9,
50 	SOF_IPC4_MOD_EXIT_MODULE_RESTORE	= 10,
51 	SOF_IPC4_MOD_DELETE_INSTANCE		= 11,
52 };
53 
54 /*
55  * Host Driver sends this message to create a new module instance.
56  */
57 struct ipc4_module_init_ext_init {
58 	/**< if it is set to 1, proc_domain should be ignored and processing */
59 	/* domain is RTOS scheduling */
60 	uint32_t rtos_domain : 1;
61 	/**< Indicates that GNA is used by a module and additional information */
62 	/* (gna_config) is passed after ExtendedData. */
63 	uint32_t gna_used    : 1;
64 	uint32_t rsvd_0      : 30;
65 	uint32_t rsvd_1[2];
66 } __attribute__((packed, aligned(4)));
67 
68 struct ipc4_module_init_ext_data {
69 	struct ipc4_module_init_ext_init extended_init;
70 
71 	/**< Data (actual size set to param_block_size) */
72 	uint32_t param_data[];
73 } __attribute__((packed, aligned(4)));
74 
75 struct ipc4_module_init_gna_config {
76 	/**< Number of GNA cycles required to process one input frame. */
77 	/* This information is used by DP scheduler to correctly schedule
78 	 * a DP module.
79 	 */
80 	uint32_t gna_cpc;
81 	uint32_t rsvd;
82 } __attribute__((packed, aligned(4)));
83 
84 struct ipc4_module_init_data {
85 	/**< Data (actual size set to param_block_size) */
86 	uint32_t param_data[0];
87 } __attribute__((packed, aligned(4)));
88 
89 /*!
90   Created instance is a child element of pipeline identified by the ppl_id
91   specified by the driver.
92 
93   The module_id should be set to an index of the module entry in the FW Image
94   Manifest.
95 
96   The instance_id assigned by the driver should be in the
97   0..ModuleEntry.max_instance_count range defined in the FW Image Manifest.
98 
99   Initial configuration of the module instance is provided by the driver in
100   the param_data array. Size of the array is specified in param_block_size
101   field of the message header.
102 
103   Refer to Module Configuration section of FW I/F Specification for details on
104   module specific initial configuration parameters.
105 
106   \remark hide_methods
107 */
108 struct ipc4_module_init_instance {
109 
110 	union {
111 		uint32_t dat;
112 
113 		struct {
114 			/**< module id */
115 			uint32_t module_id          : 16;
116 			/**< instance id */
117 			uint32_t instance_id        : 8;
118 			/**< ModuleMsg::INIT_INSTANCE */
119 			uint32_t type               : 5;
120 			/**< Msg::MSG_REQUEST */
121 			uint32_t rsp                : 1;
122 			/**< Msg::MODULE_MSG */
123 			uint32_t msg_tgt            : 1;
124 			uint32_t _reserved_0        : 1;
125 		} r;
126 	} primary;
127 
128 	union {
129 		uint32_t dat;
130 
131 		struct {
132 			/**< Size of Data::param_data[] (in dwords) */
133 			uint32_t param_block_size   : 16;
134 			/**< ID of module instance's parent pipeline */
135 			uint32_t ppl_instance_id    : 8;
136 			/**< ID of core that instance will run on */
137 			uint32_t core_id            : 4;
138 			/**< Processing domain, 0-LL, 1-DP */
139 			uint32_t proc_domain        : 1;
140 			/* reserved in cAVS  */
141 			uint32_t extended_init      : 1;
142 			uint32_t _hw_reserved_2     : 2;
143 		} r;
144 	} extension;
145 /*
146  * The following objects are optional and follow this structure in this
147  * order provided the respective object bit is set in preceding object.
148  *
149  *	struct ipc4_module_init_ext_init ext_init;
150  *	struct ipc4_module_init_ext_data ext_data;
151  *	struct ipc4_module_init_gna_config gna_config;
152  *	struct ipc4_module_init_data init_data;
153  */
154 } __attribute__((packed, aligned(4)));
155 
156 /*!
157   SW Driver sends Bind IPC message to connect two module instances together
158   creating data processing path between them.
159 
160   Unbind IPC message is sent to destroy a connection between two module instances
161   (belonging to different pipelines) previously created with Bind call.
162 
163   NOTE: when both module instances are parts of the same pipeline Unbind IPC would
164   be ignored by FW since FW does not support changing internal topology of pipeline
165   during run-time. The only way to change pipeline topology is to delete the whole
166   pipeline and create it in modified form.
167 
168   \remark hide_methods
169  */
170 struct ipc4_module_bind_unbind {
171 	union {
172 		uint32_t dat;
173 
174 		struct {
175 			/**< module id */
176 			uint32_t module_id : 16;
177 			/**< instance id */
178 			uint32_t instance_id : 8;
179 			/**< ModuleMsg::BIND / UNBIND. */
180 			uint32_t type : 5;
181 			/**< Msg::MSG_REQUEST */
182 			uint32_t rsp : 1;
183 			/**< Msg::MODULE_MSG */
184 			uint32_t msg_tgt : 1;
185 			uint32_t _reserved_0 : 1;
186 		} r;
187 	} primary;
188 
189 	union {
190 		uint32_t dat;
191 
192 		struct {
193 			/**< destination module id */
194 			uint32_t dst_module_id : 16;
195 			/**< destination instance id */
196 			uint32_t dst_instance_id : 8;
197 			/**< destination queue (pin) id */
198 			uint32_t dst_queue : SOF_IPC4_DST_QUEUE_ID_BITFIELD_SIZE;
199 			/**< source queue (pin) id */
200 			uint32_t src_queue : SOF_IPC4_SRC_QUEUE_ID_BITFIELD_SIZE;
201 			uint32_t _reserved_2 : 2;
202 		} r;
203 	} extension;
204 } __attribute__((packed, aligned(4)));
205 
206 struct ipc4_module_large_config {
207 	union {
208 		uint32_t dat;
209 
210 		struct {
211 			/**< module id */
212 			uint32_t module_id : 16;
213 			/**< instance id */
214 			uint32_t instance_id : 8;
215 			/**< ModuleMsg::LARGE_CONFIG_GET / LARGE_CONFIG_SET */
216 			uint32_t type : 5;
217 			/**< Msg::MSG_REQUEST or Msg::MSG_REPLY */
218 			uint32_t rsp : 1;
219 			/**< Msg::MODULE_MSG or Msg::FW_GEN_MSG */
220 			uint32_t msg_tgt : 1;
221 			uint32_t _reserved_0 : 1;
222 			} r;
223 		} primary;
224 
225 	union {
226 		uint32_t dat;
227 
228 		struct {
229 			/**< data size for single block, offset for multiple block case */
230 			uint32_t data_off_size : 20;
231 			/**< param type : VENDOR_CONFIG_PARAM / GENERIC_CONFIG_PARAM */
232 			uint32_t large_param_id : 8;
233 			/**< 1 if final block */
234 			uint32_t final_block : 1;
235 			/**< 1 if init block */
236 			uint32_t init_block : 1;
237 			uint32_t _reserved_2 : 2;
238 		} r;
239 	} extension;
240 } __attribute__((packed, aligned(4)));
241 
242 struct ipc4_module_large_config_reply {
243 	union {
244 		uint32_t dat;
245 
246 		struct {
247 			uint32_t status :IPC4_IXC_STATUS_BITS;
248 			/**< ModuleMsg::LARGE_CONFIG_GET / LARGE_CONFIG_SET */
249 			uint32_t type : 5;
250 			/**< Msg::MSG_REQUEST */
251 			uint32_t rsp : 1;
252 			/**< Msg::MODULE_MSG */
253 			uint32_t msg_tgt : 1;
254 			uint32_t _reserved_0 : 1;
255 			} r;
256 		} primary;
257 
258 	union {
259 		uint32_t dat;
260 
261 		struct {
262 			/**< data size/offset */
263 			uint32_t data_off_size : 20;
264 			/**< param type : VENDOR_CONFIG_PARAM / GENERIC_CONFIG_PARAM */
265 			uint32_t large_param_id : 8;
266 			/**< 1 if final block */
267 			uint32_t final_block : 1;
268 			/**< 1 if first block */
269 			uint32_t init_block : 1;
270 			uint32_t _reserved_2 : 2;
271 		} r;
272 	} extension;
273 } __attribute__((packed, aligned(4)));
274 
275 struct ipc4_module_delete_instance {
276 	union {
277 		uint32_t dat;
278 
279 		struct {
280 			uint32_t module_id : 16;
281 			uint32_t instance_id : 8;
282 			/**< ModuleMsg::DELETE_INSTANCE */
283 			uint32_t type : 5;
284 			/**< Msg::MSG_REQUEST */
285 			uint32_t rsp : 1;
286 			/**< Msg::MODULE_MSG */
287 			uint32_t msg_tgt : 1;
288 			uint32_t _reserved_0 : 1;
289 		} r;
290 	} primary;
291 
292 	union {
293 		uint32_t dat;
294 
295 		struct {
296 			uint32_t rsvd : 30;
297 			uint32_t _reserved_1 : 2;
298 		} r;
299 	} extension;
300 } __attribute__((packed, aligned(4)));
301 
302 struct ipc4_module_set_d0ix {
303 	union {
304 		uint32_t dat;
305 
306 		struct {
307 			/* module id (must be 0 - Base FW) */
308 			uint32_t module_id		: 16;
309 			/* instance id (must be 0 - core 0) */
310 			uint32_t instance_id	: 8;
311 			/* ModuleMsg::SET_D0IX */
312 			uint32_t type			: 5;
313 			/* Msg::MSG_REQUEST */
314 			uint32_t rsp			: 1;
315 			/* Msg::MODULE_MSG */
316 			uint32_t msg_tgt		: 1;
317 			uint32_t _reserved_0	: 1;
318 		} r;
319 	} primary;
320 
321 	union {
322 		uint32_t dat;
323 
324 		struct {
325 			/* legacy wake type (see WakeType) */
326 			uint32_t wake			: 1;
327 			/* streaming active now */
328 			uint32_t streaming		: 1;
329 			/* D0/D0ix transitions allowed (PG disabled) */
330 			uint32_t prevent_power_gating : 1;
331 			/* Clock gating enabled */
332 			uint32_t prevent_local_clock_gating : 1;
333 
334 			uint32_t rsvd1			: 26;
335 			uint32_t _reserved_2	: 2;
336 		} r;
337 	} extension;
338 } __attribute__((packed, aligned(4)));
339 
340 struct ipc4_dx_state_info {
341 	/* Indicates which cores are subject to change the power state */
342 	uint32_t core_mask;
343 	/* Indicates core state.
344 	 * bit[core_id] = 0 -> put core_id to D3
345 	 * bit[core_id] = 1 -> put core_id to D0
346 	 */
347 	uint32_t dx_mask;
348 } __packed __aligned(4);
349 
350 struct ipc4_module_set_dx {
351 	union {
352 		uint32_t dat;
353 
354 		struct {
355 			/* module id (must be 0 - Base FW) */
356 			uint32_t module_id			: 16;
357 			/* instance id (must be 0 - core 0) */
358 			uint32_t instance_id		: 8;
359 			/* ModuleMsg::SET_DX */
360 			uint32_t type				: 5;
361 			/* Msg::MSG_REQUEST */
362 			uint32_t rsp				: 1;
363 			/* Msg::MODULE_MSG */
364 			uint32_t msg_tgt			: 1;
365 			uint32_t _reserved_0		: 1;
366 		} r;
367 	} primary;
368 
369 	union {
370 		uint32_t dat;
371 
372 		struct {
373 			uint32_t rsvd				: 30;
374 			uint32_t _reserved_2		: 2;
375 		} r;
376 	} extension;
377 } __attribute__((packed, aligned(4)));
378 
379 struct ipc4_module_load_library {
380 	union {
381 		uint32_t dat;
382 
383 		struct {
384 			/* ID of HD/A HO DMA to load the code */
385 			uint32_t dma_id				: 5;
386 			uint32_t rsvd0				: 11;
387 			/* ID of library */
388 			uint32_t lib_id				: 4;
389 			uint32_t rsvd1				: 4;
390 			/* Global::LOAD_LIBRARY */
391 			uint32_t type				: 5;
392 			/* Msg::MSG_REQUEST */
393 			uint32_t rsp				: 1;
394 			/* Msg::FW_GEN_MSG */
395 			uint32_t msg_tgt			: 1;
396 			uint32_t _reserved_0		: 1;
397 		} r;
398 	} header;
399 
400 	union {
401 		uint32_t dat;
402 
403 		struct {
404 			uint32_t load_offset		: 30;
405 			uint32_t _reserved_2		: 2;
406 		} r;
407 	} data;
408 } __packed __aligned(4);
409 
410 #define IPC4_COMP_ID(x, y)	((x) << 16 | (y))
411 #define IPC4_MOD_ID(x) ((x) >> 16)
412 #define IPC4_INST_ID(x)	((x) & 0xffff)
413 #define IPC4_SRC_QUEUE_ID(x)	(((x) >> 16) & 0xffff)
414 #define IPC4_SINK_QUEUE_ID(x)	((x) & 0xffff)
415 
416 #endif
417