1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019 Intel Corporation. All rights reserved.
4  *
5  * Author: Artur Kloniecki <arturx.kloniecki@linux.intel.com>
6  */
7 
8 /**
9  * \file include/sof/audio/mux.h
10  * \brief Multiplexer component header file
11  * \authors Artur Kloniecki <arturx.kloniecki@linux.intel.com>
12  */
13 
14 #ifndef __SOF_AUDIO_MUX_H__
15 #define __SOF_AUDIO_MUX_H__
16 
17 #if CONFIG_COMP_MUX
18 
19 #include <sof/common.h>
20 #include <sof/platform.h>
21 #include <sof/trace/trace.h>
22 #include <sof/ut.h>
23 #include <user/trace.h>
24 #include <stdint.h>
25 #if CONFIG_IPC_MAJOR_4
26 #include <ipc4/base-config.h>
27 #endif
28 struct comp_buffer;
29 struct comp_dev;
30 
31 /** \brief Supported streams count. */
32 #if CONFIG_IPC_MAJOR_3
33 #define MUX_MAX_STREAMS 4
34 #else
35 #define MUX_MAX_STREAMS 2
36 #endif
37 #define BASE_CFG_QUEUED_ID 0
38 /** guard against invalid amount of streams defined */
39 STATIC_ASSERT(MUX_MAX_STREAMS < PLATFORM_MAX_STREAMS,
40 	      unsupported_amount_of_streams_for_mux);
41 
42 struct mux_copy_elem {
43 	uint32_t stream_id;
44 	uint32_t in_ch;
45 	uint32_t out_ch;
46 
47 	void *dest;
48 	void *src;
49 
50 	uint32_t dest_inc;
51 	uint32_t src_inc;
52 };
53 
54 struct mux_look_up {
55 	uint32_t num_elems;
56 	struct mux_copy_elem copy_elem[PLATFORM_MAX_CHANNELS];
57 };
58 
59 struct mux_stream_data {
60 	uint32_t pipeline_id;
61 	uint8_t num_channels_deprecated;	/* deprecated in ABI 3.15 */
62 	uint8_t mask[PLATFORM_MAX_CHANNELS];
63 
64 	uint8_t reserved1[8 - PLATFORM_MAX_CHANNELS]; // padding for extra channels
65 	uint8_t reserved2[3]; // padding to ensure proper alignment of following instances
66 } __attribute__((packed, aligned(4)));
67 
68 typedef void(*demux_func)(struct comp_dev *dev, struct audio_stream __sparse_cache *sink,
69 			  const struct audio_stream __sparse_cache *source, uint32_t frames,
70 			  struct mux_look_up *look_up);
71 typedef void(*mux_func)(struct comp_dev *dev, struct audio_stream __sparse_cache *sink,
72 			const struct audio_stream __sparse_cache **sources, uint32_t frames,
73 			struct mux_look_up *look_up);
74 
75 /**
76  * \brief Mux/Demux component config structure.
77  *
78  * The multiplexer/demultiplexer component copies its input audio channels
79  * into output audio channels according to a specific routing matrix.
80  * Multiplexer has multiple input audio streams and a single audio output
81  * stream. Demultiplexer has a single input stream and multiple output streams.
82  *
83  * Struct sof_mux_config includes array of mux_stream_data struct elements -
84  * streams[]. Each element of streams[] array refers to streams on "many" side
85  * of mux/demux component i.e. input streams for mux and output streams for
86  * demux.
87  *
88  * Struct mux_stream_data consists mask[] array.
89  * In the mux case, one mask[] element per input channel - each mask shows, to
90  * which output channel data should be copied.
91  * In the demux case, one mask[] element per output channel - each mask shows,
92  * from which input channel data should be taken.
93  *
94  * Mux example:
95  * Assuming that below mask array refers to x input stream:
96  * mask[] = {	0b00000001,
97  *		0b00000100 }
98  * it means that:
99  * - first input channel of stream x (mask[0]) will be copied to first output
100  *   channel (0b00000001 & BIT(0));
101  * - second input channel of stream x (mask[1]) will be copied to third output
102  *   channel (0b00000100 & BIT(2)).
103  *
104  * Demux example:
105  * Assuming that below mask array refers to x output stream:
106  * mask[] = {	0b00000001,
107  *		0b00000100 }
108  * it means that:
109  * - first input channel (0b00000001 & BIT(0)) will be copied to first output
110  *   (mask[0]) channel of stream x;
111  * - third input channel (0b00000100 & BIT(2)) will be copied to second output
112  *   (mask[1]) channel of stream x.
113  */
114 struct sof_mux_config {
115 	uint16_t frame_format_deprecated;	/* deprecated in ABI 3.15 */
116 	uint16_t num_channels_deprecated;	/* deprecated in ABI 3.15 */
117 	uint16_t num_streams;
118 
119 	uint16_t reserved; // padding to ensure proper alignment
120 
121 	struct mux_stream_data streams[];
122 } __attribute__((packed, aligned(4)));
123 
124 #if CONFIG_IPC_MAJOR_4
125 /**
126  * \brief MUX module configuration in IPC4.
127  *
128  * This module output map is statically defined by the adapter (shim) as:
129  *  - Input pin 0 channel "x" ("x" = 0.."M", "M" <=3) to output channel "x",
130  *    where "M" is number of channels on input pin 0,
131  *  - Input pin 1 (reference) channel "y" (y = 0..1) to output channel "M"+1+"y".
132  *
133  * If input pin 0 is not connected, module will not produce any output.
134  * If input pin 1 (know also as reference pin) is not connected then module will
135  * in output (for time slot meant for pin 1) generate zeros.
136  *
137  * Setting masks for streams is done according to the order of pins and channels.
138  * First the first input stream, then the reference.
139  * For example, for base config 2-channel and reference 2-channel, masks
140  * should look like: mask[] = { 0b00000001, 0b00000010 } for the first
141  * stream and mask[] = { 0b00000100, 0b00001000 } for the second
142  * (reference)
143  *           +---+           +---+
144  *           | 0 |---------> | 0 |
145  * INPUT     +---+           +---+
146  * STREAM 0  | 1 |---------> | 1 |
147  *           +---+           +---+  OUTPUT
148  *                    +----> | 2 |  STREAM
149  *           +---+    |      +---+
150  *           | 0 |----+  +-> | 3 |
151  * INPUT     +---+       |   +---+
152  * STREAM 1  | 1 |-------+
153  *           +---+
154  */
155 struct mux_data {
156 	struct ipc4_base_module_cfg base_cfg;
157 	 //! Reference pin format.
158 	struct ipc4_audio_format reference_format;
159 	 //! Output pin format.
160 	struct ipc4_audio_format output_format;
161 };
162 #endif
163 
164 struct comp_data {
165 #if CONFIG_IPC_MAJOR_4
166 	struct mux_data md;
167 #endif
168 	union {
169 		mux_func mux;
170 		demux_func demux;
171 	};
172 
173 	struct mux_look_up lookup[MUX_MAX_STREAMS];
174 	struct mux_look_up active_lookup;
175 	struct comp_data_blob_handler *model_handler;
176 	struct sof_mux_config config; /* Keep last due to flexible array member in end */
177 };
178 
179 struct comp_func_map {
180 	uint16_t frame_format;
181 	mux_func mux_proc_func;
182 	demux_func demux_proc_func;
183 };
184 
185 extern const struct comp_func_map mux_func_map[];
186 
187 void mux_prepare_look_up_table(struct processing_module *mod);
188 void demux_prepare_look_up_table(struct processing_module *mod);
189 
190 mux_func mux_get_processing_function(struct processing_module *mod);
191 demux_func demux_get_processing_function(struct processing_module *mod);
192 
193 #ifdef UNIT_TEST
194 
195 #if CONFIG_FORMAT_S16LE
196 int32_t calc_sample_s16le(const struct audio_stream *source,
197 			  uint32_t offset, uint8_t mask);
198 #endif /* CONFIG_FORMAT_S16LE */
199 #if CONFIG_FORMAT_S24LE
200 int32_t calc_sample_s24le(const struct audio_stream *source,
201 			  uint32_t offset, uint8_t mask);
202 #endif /* CONFIG_FORMAT_S24LE */
203 #if CONFIG_FORMAT_S32LE
204 int64_t calc_sample_s32le(const struct audio_stream *source,
205 			  uint32_t offset, uint8_t mask);
206 #endif /* CONFIG_FORMAT_S32LE */
207 
208 void sys_comp_module_mux_interface_init(void);
209 void sys_comp_module_demux_interface_init(void);
210 
211 #endif /* UNIT_TEST */
212 
213 #endif /* CONFIG_COMP_MUX */
214 
215 #endif /* __SOF_AUDIO_MUX_H__ */
216