1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2020 Intel Corporation. All rights reserved.
4  *
5  *
6  * \file generic.h
7  * \brief Generic Codec API header file
8  * \author Marcin Rajwa <marcin.rajwa@linux.intel.com>
9  *
10  */
11 
12 #ifndef __SOF_AUDIO_CODEC_GENERIC__
13 #define __SOF_AUDIO_CODEC_GENERIC__
14 
15 #include <sof/audio/component.h>
16 #include <sof/ut.h>
17 #include <sof/lib/memory.h>
18 
19 #define comp_get_codec(d) (&(((struct comp_data *)((d)->priv_data))->codec))
20 #define CODEC_GET_INTERFACE_ID(id) ((id) >> 0x8)
21 #define CODEC_GET_API_ID(id) ((id) & 0xFF)
22 #define API_CALL(cd, cmd, sub_cmd, value, ret) \
23 	do { \
24 		ret = (cd)->api((cd)->self, \
25 				(cmd), \
26 				(sub_cmd), \
27 				(value)); \
28 	} while (0)
29 
30 #define DECLARE_CODEC_ADAPTER(adapter, uuid, tr) \
31 static struct comp_dev *adapter_shim_new(const struct comp_driver *drv, \
32 					 struct comp_ipc_config *config, \
33 					 void *spec) \
34 { \
35 	return codec_adapter_new(drv, config, &(adapter), spec);\
36 } \
37 \
38 static const struct comp_driver comp_codec_adapter = { \
39 	.type = SOF_COMP_CODEC_ADAPTOR, \
40 	.uid = SOF_RT_UUID(uuid), \
41 	.tctx = &(tr), \
42 	.ops = { \
43 		.create = adapter_shim_new, \
44 		.prepare = codec_adapter_prepare, \
45 		.params = codec_adapter_params, \
46 		.copy = codec_adapter_copy, \
47 		.cmd = codec_adapter_cmd, \
48 		.trigger = codec_adapter_trigger, \
49 		.reset = codec_adapter_reset, \
50 		.free = codec_adapter_free, \
51 	}, \
52 }; \
53 \
54 static SHARED_DATA struct comp_driver_info comp_codec_adapter_info = { \
55 	.drv = &comp_codec_adapter, \
56 }; \
57 \
58 UT_STATIC void sys_comp_codec_##adapter_init(void) \
59 { \
60 	comp_register(platform_shared_get(&comp_codec_adapter_info, \
61 					  sizeof(comp_codec_adapter_info))); \
62 } \
63 \
64 DECLARE_MODULE(sys_comp_codec_##adapter_init)
65 
66 /*****************************************************************************/
67 /* Codec generic data types						     */
68 /*****************************************************************************/
69 /**
70  * \struct codec_interface
71  * \brief Codec specific interfaces
72  */
73 struct codec_interface {
74 	/**
75 	 * The unique ID for a codec, used for initialization as well as
76 	 * parameters loading.
77 	 */
78 	uint32_t id;
79 	/**
80 	 * Codec specific initialization procedure, called as part of
81 	 * codec_adapter component creation in .new()
82 	 */
83 	int (*init)(struct comp_dev *dev);
84 	/**
85 	 * Codec specific prepare procedure, called as part of codec_adapter
86 	 * component preparation in .prepare()
87 	 */
88 	int (*prepare)(struct comp_dev *dev);
89 	/**
90 	 * Codec specific. Returns the number of PCM output
91 	 * samples after decoding one input compressed frame.
92 	 * Codecs will return 0 for don't care.
93 	 */
94 	int (*get_samples)(struct comp_dev *dev);
95 	/**
96 	 * Codec specific init processing procedure, called as a part of
97 	 * codec_adapter component copy in .copy(). Typically in this
98 	 * phase a processing algorithm searches for the valid header,
99 	 * does header decoding to get the parameters and initializes
100 	 * state and configuration structures.
101 	 */
102 	int (*init_process)(struct comp_dev *dev);
103 	/**
104 	 * Codec specific processing procedure, called as part of codec_adapter
105 	 * component copy in .copy(). This procedure is responsible to consume
106 	 * samples provided by the codec_adapter and produce/output the processed
107 	 * ones back to codec_adapter.
108 	 */
109 	int (*process)(struct comp_dev *dev);
110 	/**
111 	 * Codec specific apply config procedure, called by codec_adapter every time
112 	 * a new RUNTIME configuration has been sent if the adapter has been
113 	 * prepared. This will not be called for SETUP cfg.
114 	 */
115 	int (*apply_config)(struct comp_dev *dev);
116 	/**
117 	 * Codec specific reset procedure, called as part of codec_adapter component
118 	 * reset in .reset(). This should reset all parameters to their initial stage
119 	 * but leave allocated memory intact.
120 	 */
121 	int (*reset)(struct comp_dev *dev);
122 	/**
123 	 * Codec specific free procedure, called as part of codec_adapter component
124 	 * free in .free(). This should free all memory allocated by codec.
125 	 */
126 	int (*free)(struct comp_dev *dev);
127 };
128 
129 /**
130  * \enum codec_cfg_type
131  * \brief Specific configuration types which can be either:
132  */
133 enum codec_cfg_type {
134 	CODEC_CFG_SETUP, /**< Used to pass setup parameters */
135 	CODEC_CFG_RUNTIME /**< Used every time runtime parameters has been loaded. */
136 };
137 
138 /**
139  * \enum codec_state
140  * \brief Codec specific states
141  */
142 enum codec_state {
143 	CODEC_DISABLED, /**< Codec isn't initialized yet or has been freed.*/
144 	CODEC_INITIALIZED, /**< Codec initialized or reset. */
145 	CODEC_IDLE, /**< Codec is idle now. */
146 	CODEC_PROCESSING, /**< Codec is processing samples now. */
147 };
148 
149 /** codec adapter setup config parameters */
150 struct ca_config {
151 	uint32_t codec_id;
152 	uint32_t reserved;
153 	uint32_t sample_rate;
154 	uint32_t sample_width;
155 	uint32_t channels;
156 };
157 
158 /**
159  * \struct codec_config
160  * \brief Codec TLV parameters container - used for both config types.
161  * For example if one want to set the sample_rate to 16 [kHz] and this
162  * parameter was assigned to id 0x01, its max size is four bytes then the
163  * configuration filed should look like this (note little-endian format):
164  * 0x01 0x00 0x00 0x00, 0x0C 0x00 0x00 0x00, 0x10 0x00 0x00 0x00.
165  */
166 struct codec_param {
167 	/**
168 	 * Specifies the unique id of a parameter. For example the parameter
169 	 * sample_rate may have an id of 0x01.
170 	 */
171 	uint32_t id;
172 	uint32_t size; /**< The size of whole parameter - id + size + data */
173 	int32_t data[]; /**< A pointer to memory where config is stored.*/
174 };
175 
176 /**
177  * \struct codec_config
178  * \brief Codec config container, used for both config types.
179  */
180 struct codec_config {
181 	size_t size; /**< Specifies the size of whole config */
182 	bool avail; /**< Marks config as available to use.*/
183 	void *data; /**< tlv config, a pointer to memory where config is stored. */
184 };
185 
186 /**
187  * \struct codec_memory
188  * \brief codec memory block - used for every memory allocated by codec
189  */
190 struct codec_memory {
191 	void *ptr; /**< A pointr to particular memory block */
192 	struct list_item mem_list; /**< list of memory allocated by codec */
193 };
194 
195 /**
196  * \struct codec_processing_data
197  * \brief Processing data shared between particular codec & codec_adapter
198  */
199 struct codec_processing_data {
200 	uint32_t in_buff_size; /**< Specifies the size of codec input buffer. */
201 	uint32_t out_buff_size; /**< Specifies the size of codec output buffer.*/
202 	uint32_t avail; /**< Specifies how much data is available for codec to process.*/
203 	uint32_t produced; /**< Specifies how much data the codec produced in its last task.*/
204 	uint32_t consumed; /**< Specified how much data the codec consumed in its last task */
205 	uint32_t init_done; /**< Specifies if the codec initialization is finished */
206 	void *in_buff; /**< A pointer to codec input buffer. */
207 	void *out_buff; /**< A pointer to codec output buffer. */
208 };
209 
210 /** private, runtime codec data */
211 struct codec_data {
212 	uint32_t id;
213 	enum codec_state state;
214 	void *private; /**< self object, memory tables etc here */
215 	void *runtime_params;
216 	struct codec_config s_cfg; /**< setup config */
217 	struct codec_config r_cfg; /**< runtime config */
218 	struct codec_interface *ops; /**< codec specific operations */
219 	struct codec_memory memory; /**< memory allocated by codec */
220 	struct codec_processing_data cpd; /**< shared data comp <-> codec */
221 };
222 
223 /* codec_adapter private, runtime data */
224 struct comp_data {
225 	struct ca_config ca_config;
226 	struct codec_data codec; /**< codec private data */
227 	struct comp_buffer *ca_sink;
228 	struct comp_buffer *ca_source;
229 	struct comp_buffer *local_buff;
230 	struct sof_ipc_stream_params stream_params;
231 	uint32_t period_bytes; /** pipeline period bytes */
232 	uint32_t deep_buff_bytes; /**< copy start threshold */
233 };
234 
235 /*****************************************************************************/
236 /* Codec generic interfaces						     */
237 /*****************************************************************************/
238 int codec_load_config(struct comp_dev *dev, void *cfg, size_t size,
239 		      enum codec_cfg_type type);
240 int codec_init(struct comp_dev *dev, struct codec_interface *interface);
241 void *codec_allocate_memory(struct comp_dev *dev, uint32_t size,
242 			    uint32_t alignment);
243 int codec_free_memory(struct comp_dev *dev, void *ptr);
244 void codec_free_all_memory(struct comp_dev *dev);
245 int codec_prepare(struct comp_dev *dev);
246 int codec_get_samples(struct comp_dev *dev);
247 int codec_init_process(struct comp_dev *dev);
248 int codec_process(struct comp_dev *dev);
249 int codec_apply_runtime_config(struct comp_dev *dev);
250 int codec_reset(struct comp_dev *dev);
251 int codec_free(struct comp_dev *dev);
252 
253 struct comp_dev *codec_adapter_new(const struct comp_driver *drv,
254 				   struct comp_ipc_config *config,
255 				   struct codec_interface *interface,
256 				   void *spec);
257 int codec_adapter_prepare(struct comp_dev *dev);
258 int codec_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *params);
259 int codec_adapter_copy(struct comp_dev *dev);
260 int codec_adapter_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size);
261 int codec_adapter_trigger(struct comp_dev *dev, int cmd);
262 void codec_adapter_free(struct comp_dev *dev);
263 int codec_adapter_reset(struct comp_dev *dev);
264 
265 #endif /* __SOF_AUDIO_CODEC_GENERIC__ */
266