summaryrefslogtreecommitdiff
path: root/src/topology/tplg_local.h
blob: 518b81eded1f234f9ca83ca75854aca17e918c2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/*
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 */

#include <limits.h>
#include <stdint.h>
#include <stdbool.h>

#include "local.h"
#include "list.h"
#include "topology.h"

#include <sound/asound.h>
#include <sound/asoc.h>
#include <sound/tlv.h>

#define TPLG_DEBUG
#ifdef TPLG_DEBUG
#define tplg_dbg SNDERR
#else
#define tplg_dbg(fmt, arg...) do { } while (0)
#endif

#define MAX_FILE		256
#define TPLG_MAX_PRIV_SIZE	(1024 * 128)
#define ALSA_TPLG_DIR	ALSA_CONFIG_DIR "/topology"

/** The name of the environment variable containing the tplg directory */
#define ALSA_CONFIG_TPLG_VAR "ALSA_CONFIG_TPLG"

struct tplg_ref;
struct tplg_elem;

struct snd_tplg {

	/* opaque vendor data */
	int vendor_fd;
	char *vendor_name;

	/* out file */
	int out_fd;

	int verbose;
	unsigned int version;

	/* runtime state */
	unsigned int next_hdr_pos;
	int index;
	int channel_idx;

	/* manifest */
	struct snd_soc_tplg_manifest manifest;
	const void *manifest_pdata;	/* copied by builder at file write */

	/* list of each element type */
	struct list_head tlv_list;
	struct list_head widget_list;
	struct list_head pcm_list;
	struct list_head be_list;
	struct list_head cc_list;
	struct list_head route_list;
	struct list_head text_list;
	struct list_head pdata_list;
	struct list_head token_list;
	struct list_head tuple_list;
	struct list_head pcm_config_list;
	struct list_head pcm_caps_list;

	/* type-specific control lists */
	struct list_head mixer_list;
	struct list_head enum_list;
	struct list_head bytes_ext_list;
};

/* object text references */
struct tplg_ref {
	unsigned int type;
	struct tplg_elem *elem;
	char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
	struct list_head list;
};

/* element for vendor tokens */
struct tplg_token {
	char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
	unsigned int value;
};

struct tplg_vendor_tokens {
	unsigned int num_tokens;
	struct tplg_token token[0];
};

/* element for vendor tuples */
struct tplg_tuple {
	char token[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
	union {
		char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
		char uuid[16];
		unsigned int value;
	};
};

struct tplg_tuple_set {
	unsigned int  type; /* uuid, bool, byte, short, word, string*/
	unsigned int  num_tuples;
	struct tplg_tuple tuple[0];
};

struct tplg_vendor_tuples {
	unsigned int  num_sets;
	struct tplg_tuple_set **set;
};

/* topology element */
struct tplg_elem {

	char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];

	/* storage for texts and data if this is text or data elem*/
	char texts[SND_SOC_TPLG_NUM_TEXTS][SNDRV_CTL_ELEM_ID_NAME_MAXLEN];

	int index;
	enum snd_tplg_type type;

	int size; /* total size of this object inc pdata and ref objects */
	int compound_elem; /* dont write this element as individual elem */
	int vendor_type; /* vendor type for private data */

	/* UAPI object for this elem */
	union {
		void *obj;
		struct snd_soc_tplg_mixer_control *mixer_ctrl;
		struct snd_soc_tplg_enum_control *enum_ctrl;
		struct snd_soc_tplg_bytes_control *bytes_ext;
		struct snd_soc_tplg_dapm_widget *widget;
		struct snd_soc_tplg_pcm *pcm;
		struct snd_soc_tplg_link_config *be;
		struct snd_soc_tplg_link_config *cc;
		struct snd_soc_tplg_dapm_graph_elem *route;
		struct snd_soc_tplg_stream *stream_cfg;
		struct snd_soc_tplg_stream_caps *stream_caps;

		/* these do not map to UAPI structs but are internal only */
		struct snd_soc_tplg_ctl_tlv *tlv;
		struct snd_soc_tplg_private *data;
		struct tplg_vendor_tokens *tokens;
		struct tplg_vendor_tuples *tuples;
	};

	/* an element may refer to other elements:
	 * a mixer control may refer to a tlv,
	 * a widget may refer to a mixer control array,
	 * a graph may refer to some widgets.
	 */
	struct list_head ref_list;
	struct list_head list; /* list of all elements with same type */

	void (*free)(void *obj);
};

struct map_elem {
	const char *name;
	int id;
};

int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg,
	int (*fcn)(snd_tplg_t *, snd_config_t *, void *),
	void *private);

int tplg_write_data(snd_tplg_t *tplg);

int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
	void *private ATTRIBUTE_UNUSED);

int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,
	void *private ATTRIBUTE_UNUSED);

int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
	void *private ATTRIBUTE_UNUSED);

int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
	void *private ATTRIBUTE_UNUSED);

int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
	void *private ATTRIBUTE_UNUSED);

void tplg_free_tuples(void *obj);

int tplg_parse_control_bytes(snd_tplg_t *tplg,
	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);

int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
	void *private ATTRIBUTE_UNUSED);

int tplg_parse_control_mixer(snd_tplg_t *tplg,
	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);

int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
	void *private ATTRIBUTE_UNUSED);

int tplg_parse_dapm_widget(snd_tplg_t *tplg,
	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);

int tplg_parse_stream_caps(snd_tplg_t *tplg,
	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);

int tplg_parse_pcm(snd_tplg_t *tplg,
	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);

int tplg_parse_be(snd_tplg_t *tplg,
	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);

int tplg_parse_cc(snd_tplg_t *tplg,
	snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);

int tplg_build_data(snd_tplg_t *tplg);
int tplg_build_controls(snd_tplg_t *tplg);
int tplg_build_widgets(snd_tplg_t *tplg);
int tplg_build_routes(snd_tplg_t *tplg);
int tplg_build_pcm_dai(snd_tplg_t *tplg, unsigned int type);

int tplg_copy_data(snd_tplg_t *tplg, struct tplg_elem *elem,
		   struct tplg_ref *ref);

int tplg_parse_data_refs(snd_config_t *cfg, struct tplg_elem *elem);

int tplg_ref_add(struct tplg_elem *elem, int type, const char* id);
int tplg_ref_add_elem(struct tplg_elem *elem, struct tplg_elem *elem_ref);

struct tplg_elem *tplg_elem_new(void);
void tplg_elem_free(struct tplg_elem *elem);
void tplg_elem_free_list(struct list_head *base);
struct tplg_elem *tplg_elem_lookup(struct list_head *base,
				const char* id,
				unsigned int type);
struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
	snd_config_t *cfg, const char *name, enum snd_tplg_type type);

static inline void elem_copy_text(char *dest, const char *src, int len)
{
	strncpy(dest, src, len);
	dest[len - 1] = 0;
}

int tplg_parse_channel(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
	snd_config_t *cfg, void *private);

int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
	snd_config_t *cfg, void *private);
int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
	snd_config_t *cfg, void *private);

struct tplg_elem *lookup_pcm_dai_stream(struct list_head *base,
	const char* id);

int tplg_add_mixer_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
int tplg_add_enum_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
int tplg_add_bytes_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
int tplg_add_graph_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);

int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
		   struct tplg_elem **e);
int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
		  struct tplg_elem **e);
int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
		   struct tplg_elem **e);

int tplg_build_pcm(snd_tplg_t *tplg, unsigned int type);
int tplg_build_link_cfg(snd_tplg_t *tplg, unsigned int type);
int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);