blob: 086fe4d27f60b26394bff5820a2ae9302abce8a8 [file] [log] [blame]
Liam Girdwood8a978232015-05-29 19:06:14 +01001/*
2 * soc-topology.c -- ALSA SoC Topology
3 *
4 * Copyright (C) 2012 Texas Instruments Inc.
5 * Copyright (C) 2015 Intel Corporation.
6 *
7 * Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
8 * K, Mythri P <mythri.p.k@intel.com>
9 * Prusty, Subhransu S <subhransu.s.prusty@intel.com>
10 * B, Jayachandran <jayachandran.b@intel.com>
11 * Abdullah, Omair M <omair.m.abdullah@intel.com>
12 * Jin, Yao <yao.jin@intel.com>
13 * Lin, Mengdong <mengdong.lin@intel.com>
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version.
19 *
20 * Add support to read audio firmware topology alongside firmware text. The
21 * topology data can contain kcontrols, DAPM graphs, widgets, DAIs, DAI links,
22 * equalizers, firmware, coefficients etc.
23 *
24 * This file only manages the core ALSA and ASoC components, all other bespoke
25 * firmware topology data is passed to component drivers for bespoke handling.
26 */
27
28#include <linux/kernel.h>
29#include <linux/export.h>
30#include <linux/list.h>
31#include <linux/firmware.h>
32#include <linux/slab.h>
33#include <sound/soc.h>
34#include <sound/soc-dapm.h>
35#include <sound/soc-topology.h>
Mengdong Lin28a87ee2015-08-05 14:41:13 +010036#include <sound/tlv.h>
Liam Girdwood8a978232015-05-29 19:06:14 +010037
38/*
39 * We make several passes over the data (since it wont necessarily be ordered)
40 * and process objects in the following order. This guarantees the component
41 * drivers will be ready with any vendor data before the mixers and DAPM objects
42 * are loaded (that may make use of the vendor data).
43 */
44#define SOC_TPLG_PASS_MANIFEST 0
45#define SOC_TPLG_PASS_VENDOR 1
46#define SOC_TPLG_PASS_MIXER 2
47#define SOC_TPLG_PASS_WIDGET 3
Mengdong Lin1a8e7fa2015-08-10 22:48:30 +080048#define SOC_TPLG_PASS_PCM_DAI 4
49#define SOC_TPLG_PASS_GRAPH 5
50#define SOC_TPLG_PASS_PINS 6
Mengdong Lin0038be92016-07-26 14:32:37 +080051#define SOC_TPLG_PASS_BE_DAI 7
Liam Girdwood8a978232015-05-29 19:06:14 +010052
53#define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST
Mengdong Lin0038be92016-07-26 14:32:37 +080054#define SOC_TPLG_PASS_END SOC_TPLG_PASS_BE_DAI
Liam Girdwood8a978232015-05-29 19:06:14 +010055
56struct soc_tplg {
57 const struct firmware *fw;
58
59 /* runtime FW parsing */
60 const u8 *pos; /* read postion */
61 const u8 *hdr_pos; /* header position */
62 unsigned int pass; /* pass number */
63
64 /* component caller */
65 struct device *dev;
66 struct snd_soc_component *comp;
67 u32 index; /* current block index */
68 u32 req_index; /* required index, only loaded/free matching blocks */
69
Mengdong Lin88a17d82015-08-18 18:11:51 +080070 /* vendor specific kcontrol operations */
Liam Girdwood8a978232015-05-29 19:06:14 +010071 const struct snd_soc_tplg_kcontrol_ops *io_ops;
72 int io_ops_count;
73
Mengdong Lin1a3232d2015-08-18 18:12:20 +080074 /* vendor specific bytes ext handlers, for TLV bytes controls */
75 const struct snd_soc_tplg_bytes_ext_ops *bytes_ext_ops;
76 int bytes_ext_ops_count;
77
Liam Girdwood8a978232015-05-29 19:06:14 +010078 /* optional fw loading callbacks to component drivers */
79 struct snd_soc_tplg_ops *ops;
80};
81
82static int soc_tplg_process_headers(struct soc_tplg *tplg);
83static void soc_tplg_complete(struct soc_tplg *tplg);
84struct snd_soc_dapm_widget *
85snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
86 const struct snd_soc_dapm_widget *widget);
87struct snd_soc_dapm_widget *
88snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
89 const struct snd_soc_dapm_widget *widget);
90
91/* check we dont overflow the data for this control chunk */
92static int soc_tplg_check_elem_count(struct soc_tplg *tplg, size_t elem_size,
93 unsigned int count, size_t bytes, const char *elem_type)
94{
95 const u8 *end = tplg->pos + elem_size * count;
96
97 if (end > tplg->fw->data + tplg->fw->size) {
98 dev_err(tplg->dev, "ASoC: %s overflow end of data\n",
99 elem_type);
100 return -EINVAL;
101 }
102
103 /* check there is enough room in chunk for control.
104 extra bytes at the end of control are for vendor data here */
105 if (elem_size * count > bytes) {
106 dev_err(tplg->dev,
107 "ASoC: %s count %d of size %zu is bigger than chunk %zu\n",
108 elem_type, count, elem_size, bytes);
109 return -EINVAL;
110 }
111
112 return 0;
113}
114
115static inline int soc_tplg_is_eof(struct soc_tplg *tplg)
116{
117 const u8 *end = tplg->hdr_pos;
118
119 if (end >= tplg->fw->data + tplg->fw->size)
120 return 1;
121 return 0;
122}
123
124static inline unsigned long soc_tplg_get_hdr_offset(struct soc_tplg *tplg)
125{
126 return (unsigned long)(tplg->hdr_pos - tplg->fw->data);
127}
128
129static inline unsigned long soc_tplg_get_offset(struct soc_tplg *tplg)
130{
131 return (unsigned long)(tplg->pos - tplg->fw->data);
132}
133
134/* mapping of Kcontrol types and associated operations. */
135static const struct snd_soc_tplg_kcontrol_ops io_ops[] = {
136 {SND_SOC_TPLG_CTL_VOLSW, snd_soc_get_volsw,
137 snd_soc_put_volsw, snd_soc_info_volsw},
138 {SND_SOC_TPLG_CTL_VOLSW_SX, snd_soc_get_volsw_sx,
139 snd_soc_put_volsw_sx, NULL},
140 {SND_SOC_TPLG_CTL_ENUM, snd_soc_get_enum_double,
141 snd_soc_put_enum_double, snd_soc_info_enum_double},
142 {SND_SOC_TPLG_CTL_ENUM_VALUE, snd_soc_get_enum_double,
143 snd_soc_put_enum_double, NULL},
144 {SND_SOC_TPLG_CTL_BYTES, snd_soc_bytes_get,
145 snd_soc_bytes_put, snd_soc_bytes_info},
146 {SND_SOC_TPLG_CTL_RANGE, snd_soc_get_volsw_range,
147 snd_soc_put_volsw_range, snd_soc_info_volsw_range},
148 {SND_SOC_TPLG_CTL_VOLSW_XR_SX, snd_soc_get_xr_sx,
149 snd_soc_put_xr_sx, snd_soc_info_xr_sx},
150 {SND_SOC_TPLG_CTL_STROBE, snd_soc_get_strobe,
151 snd_soc_put_strobe, NULL},
152 {SND_SOC_TPLG_DAPM_CTL_VOLSW, snd_soc_dapm_get_volsw,
Jeeja KP2c57d4782015-07-14 13:10:47 +0530153 snd_soc_dapm_put_volsw, snd_soc_info_volsw},
Liam Girdwood8a978232015-05-29 19:06:14 +0100154 {SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE, snd_soc_dapm_get_enum_double,
155 snd_soc_dapm_put_enum_double, snd_soc_info_enum_double},
156 {SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT, snd_soc_dapm_get_enum_double,
157 snd_soc_dapm_put_enum_double, NULL},
158 {SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE, snd_soc_dapm_get_enum_double,
159 snd_soc_dapm_put_enum_double, NULL},
160 {SND_SOC_TPLG_DAPM_CTL_PIN, snd_soc_dapm_get_pin_switch,
161 snd_soc_dapm_put_pin_switch, snd_soc_dapm_info_pin_switch},
162};
163
164struct soc_tplg_map {
165 int uid;
166 int kid;
167};
168
169/* mapping of widget types from UAPI IDs to kernel IDs */
170static const struct soc_tplg_map dapm_map[] = {
171 {SND_SOC_TPLG_DAPM_INPUT, snd_soc_dapm_input},
172 {SND_SOC_TPLG_DAPM_OUTPUT, snd_soc_dapm_output},
173 {SND_SOC_TPLG_DAPM_MUX, snd_soc_dapm_mux},
174 {SND_SOC_TPLG_DAPM_MIXER, snd_soc_dapm_mixer},
175 {SND_SOC_TPLG_DAPM_PGA, snd_soc_dapm_pga},
176 {SND_SOC_TPLG_DAPM_OUT_DRV, snd_soc_dapm_out_drv},
177 {SND_SOC_TPLG_DAPM_ADC, snd_soc_dapm_adc},
178 {SND_SOC_TPLG_DAPM_DAC, snd_soc_dapm_dac},
179 {SND_SOC_TPLG_DAPM_SWITCH, snd_soc_dapm_switch},
180 {SND_SOC_TPLG_DAPM_PRE, snd_soc_dapm_pre},
181 {SND_SOC_TPLG_DAPM_POST, snd_soc_dapm_post},
182 {SND_SOC_TPLG_DAPM_AIF_IN, snd_soc_dapm_aif_in},
183 {SND_SOC_TPLG_DAPM_AIF_OUT, snd_soc_dapm_aif_out},
184 {SND_SOC_TPLG_DAPM_DAI_IN, snd_soc_dapm_dai_in},
185 {SND_SOC_TPLG_DAPM_DAI_OUT, snd_soc_dapm_dai_out},
186 {SND_SOC_TPLG_DAPM_DAI_LINK, snd_soc_dapm_dai_link},
187};
188
189static int tplc_chan_get_reg(struct soc_tplg *tplg,
190 struct snd_soc_tplg_channel *chan, int map)
191{
192 int i;
193
194 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) {
195 if (chan[i].id == map)
196 return chan[i].reg;
197 }
198
199 return -EINVAL;
200}
201
202static int tplc_chan_get_shift(struct soc_tplg *tplg,
203 struct snd_soc_tplg_channel *chan, int map)
204{
205 int i;
206
207 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) {
208 if (chan[i].id == map)
209 return chan[i].shift;
210 }
211
212 return -EINVAL;
213}
214
215static int get_widget_id(int tplg_type)
216{
217 int i;
218
219 for (i = 0; i < ARRAY_SIZE(dapm_map); i++) {
220 if (tplg_type == dapm_map[i].uid)
221 return dapm_map[i].kid;
222 }
223
224 return -EINVAL;
225}
226
Liam Girdwood8a978232015-05-29 19:06:14 +0100227static inline void soc_bind_err(struct soc_tplg *tplg,
228 struct snd_soc_tplg_ctl_hdr *hdr, int index)
229{
230 dev_err(tplg->dev,
231 "ASoC: invalid control type (g,p,i) %d:%d:%d index %d at 0x%lx\n",
232 hdr->ops.get, hdr->ops.put, hdr->ops.info, index,
233 soc_tplg_get_offset(tplg));
234}
235
236static inline void soc_control_err(struct soc_tplg *tplg,
237 struct snd_soc_tplg_ctl_hdr *hdr, const char *name)
238{
239 dev_err(tplg->dev,
240 "ASoC: no complete mixer IO handler for %s type (g,p,i) %d:%d:%d at 0x%lx\n",
241 name, hdr->ops.get, hdr->ops.put, hdr->ops.info,
242 soc_tplg_get_offset(tplg));
243}
244
245/* pass vendor data to component driver for processing */
246static int soc_tplg_vendor_load_(struct soc_tplg *tplg,
247 struct snd_soc_tplg_hdr *hdr)
248{
249 int ret = 0;
250
251 if (tplg->comp && tplg->ops && tplg->ops->vendor_load)
252 ret = tplg->ops->vendor_load(tplg->comp, hdr);
253 else {
254 dev_err(tplg->dev, "ASoC: no vendor load callback for ID %d\n",
255 hdr->vendor_type);
256 return -EINVAL;
257 }
258
259 if (ret < 0)
260 dev_err(tplg->dev,
261 "ASoC: vendor load failed at hdr offset %ld/0x%lx for type %d:%d\n",
262 soc_tplg_get_hdr_offset(tplg),
263 soc_tplg_get_hdr_offset(tplg),
264 hdr->type, hdr->vendor_type);
265 return ret;
266}
267
268/* pass vendor data to component driver for processing */
269static int soc_tplg_vendor_load(struct soc_tplg *tplg,
270 struct snd_soc_tplg_hdr *hdr)
271{
272 if (tplg->pass != SOC_TPLG_PASS_VENDOR)
273 return 0;
274
275 return soc_tplg_vendor_load_(tplg, hdr);
276}
277
278/* optionally pass new dynamic widget to component driver. This is mainly for
279 * external widgets where we can assign private data/ops */
280static int soc_tplg_widget_load(struct soc_tplg *tplg,
281 struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w)
282{
283 if (tplg->comp && tplg->ops && tplg->ops->widget_load)
284 return tplg->ops->widget_load(tplg->comp, w, tplg_w);
285
286 return 0;
287}
288
Mengdong Lin64527e82016-01-15 16:13:28 +0800289/* pass DAI configurations to component driver for extra intialization */
290static int soc_tplg_dai_load(struct soc_tplg *tplg,
291 struct snd_soc_dai_driver *dai_drv)
Liam Girdwood8a978232015-05-29 19:06:14 +0100292{
Mengdong Lin64527e82016-01-15 16:13:28 +0800293 if (tplg->comp && tplg->ops && tplg->ops->dai_load)
294 return tplg->ops->dai_load(tplg->comp, dai_drv);
Liam Girdwood8a978232015-05-29 19:06:14 +0100295
296 return 0;
297}
298
Mengdong Linacfc7d42016-01-15 16:13:37 +0800299/* pass link configurations to component driver for extra intialization */
300static int soc_tplg_dai_link_load(struct soc_tplg *tplg,
301 struct snd_soc_dai_link *link)
302{
303 if (tplg->comp && tplg->ops && tplg->ops->link_load)
304 return tplg->ops->link_load(tplg->comp, link);
305
306 return 0;
307}
308
Liam Girdwood8a978232015-05-29 19:06:14 +0100309/* tell the component driver that all firmware has been loaded in this request */
310static void soc_tplg_complete(struct soc_tplg *tplg)
311{
312 if (tplg->comp && tplg->ops && tplg->ops->complete)
313 tplg->ops->complete(tplg->comp);
314}
315
316/* add a dynamic kcontrol */
317static int soc_tplg_add_dcontrol(struct snd_card *card, struct device *dev,
318 const struct snd_kcontrol_new *control_new, const char *prefix,
319 void *data, struct snd_kcontrol **kcontrol)
320{
321 int err;
322
323 *kcontrol = snd_soc_cnew(control_new, data, control_new->name, prefix);
324 if (*kcontrol == NULL) {
325 dev_err(dev, "ASoC: Failed to create new kcontrol %s\n",
326 control_new->name);
327 return -ENOMEM;
328 }
329
330 err = snd_ctl_add(card, *kcontrol);
331 if (err < 0) {
332 dev_err(dev, "ASoC: Failed to add %s: %d\n",
333 control_new->name, err);
334 return err;
335 }
336
337 return 0;
338}
339
340/* add a dynamic kcontrol for component driver */
341static int soc_tplg_add_kcontrol(struct soc_tplg *tplg,
342 struct snd_kcontrol_new *k, struct snd_kcontrol **kcontrol)
343{
344 struct snd_soc_component *comp = tplg->comp;
345
346 return soc_tplg_add_dcontrol(comp->card->snd_card,
347 comp->dev, k, NULL, comp, kcontrol);
348}
349
350/* remove a mixer kcontrol */
351static void remove_mixer(struct snd_soc_component *comp,
352 struct snd_soc_dobj *dobj, int pass)
353{
354 struct snd_card *card = comp->card->snd_card;
355 struct soc_mixer_control *sm =
356 container_of(dobj, struct soc_mixer_control, dobj);
357 const unsigned int *p = NULL;
358
359 if (pass != SOC_TPLG_PASS_MIXER)
360 return;
361
362 if (dobj->ops && dobj->ops->control_unload)
363 dobj->ops->control_unload(comp, dobj);
364
365 if (sm->dobj.control.kcontrol->tlv.p)
366 p = sm->dobj.control.kcontrol->tlv.p;
367 snd_ctl_remove(card, sm->dobj.control.kcontrol);
368 list_del(&sm->dobj.list);
369 kfree(sm);
370 kfree(p);
371}
372
373/* remove an enum kcontrol */
374static void remove_enum(struct snd_soc_component *comp,
375 struct snd_soc_dobj *dobj, int pass)
376{
377 struct snd_card *card = comp->card->snd_card;
378 struct soc_enum *se = container_of(dobj, struct soc_enum, dobj);
379 int i;
380
381 if (pass != SOC_TPLG_PASS_MIXER)
382 return;
383
384 if (dobj->ops && dobj->ops->control_unload)
385 dobj->ops->control_unload(comp, dobj);
386
387 snd_ctl_remove(card, se->dobj.control.kcontrol);
388 list_del(&se->dobj.list);
389
390 kfree(se->dobj.control.dvalues);
391 for (i = 0; i < se->items; i++)
392 kfree(se->dobj.control.dtexts[i]);
393 kfree(se);
394}
395
396/* remove a byte kcontrol */
397static void remove_bytes(struct snd_soc_component *comp,
398 struct snd_soc_dobj *dobj, int pass)
399{
400 struct snd_card *card = comp->card->snd_card;
401 struct soc_bytes_ext *sb =
402 container_of(dobj, struct soc_bytes_ext, dobj);
403
404 if (pass != SOC_TPLG_PASS_MIXER)
405 return;
406
407 if (dobj->ops && dobj->ops->control_unload)
408 dobj->ops->control_unload(comp, dobj);
409
410 snd_ctl_remove(card, sb->dobj.control.kcontrol);
411 list_del(&sb->dobj.list);
412 kfree(sb);
413}
414
415/* remove a widget and it's kcontrols - routes must be removed first */
416static void remove_widget(struct snd_soc_component *comp,
417 struct snd_soc_dobj *dobj, int pass)
418{
419 struct snd_card *card = comp->card->snd_card;
420 struct snd_soc_dapm_widget *w =
421 container_of(dobj, struct snd_soc_dapm_widget, dobj);
422 int i;
423
424 if (pass != SOC_TPLG_PASS_WIDGET)
425 return;
426
427 if (dobj->ops && dobj->ops->widget_unload)
428 dobj->ops->widget_unload(comp, dobj);
429
430 /*
431 * Dynamic Widgets either have 1 enum kcontrol or 1..N mixers.
432 * The enum may either have an array of values or strings.
433 */
434 if (dobj->widget.kcontrol_enum) {
435 /* enumerated widget mixer */
436 struct soc_enum *se =
437 (struct soc_enum *)w->kcontrols[0]->private_value;
438
439 snd_ctl_remove(card, w->kcontrols[0]);
440
441 kfree(se->dobj.control.dvalues);
442 for (i = 0; i < se->items; i++)
443 kfree(se->dobj.control.dtexts[i]);
444
445 kfree(se);
446 kfree(w->kcontrol_news);
447 } else {
448 /* non enumerated widget mixer */
449 for (i = 0; i < w->num_kcontrols; i++) {
450 struct snd_kcontrol *kcontrol = w->kcontrols[i];
451 struct soc_mixer_control *sm =
452 (struct soc_mixer_control *) kcontrol->private_value;
453
454 kfree(w->kcontrols[i]->tlv.p);
455
456 snd_ctl_remove(card, w->kcontrols[i]);
457 kfree(sm);
458 }
459 kfree(w->kcontrol_news);
460 }
461 /* widget w is freed by soc-dapm.c */
462}
463
Mengdong Lin64527e82016-01-15 16:13:28 +0800464/* remove DAI configurations */
465static void remove_dai(struct snd_soc_component *comp,
Liam Girdwood8a978232015-05-29 19:06:14 +0100466 struct snd_soc_dobj *dobj, int pass)
467{
Mengdong Lin64527e82016-01-15 16:13:28 +0800468 struct snd_soc_dai_driver *dai_drv =
469 container_of(dobj, struct snd_soc_dai_driver, dobj);
470
Liam Girdwood8a978232015-05-29 19:06:14 +0100471 if (pass != SOC_TPLG_PASS_PCM_DAI)
472 return;
473
Mengdong Lin64527e82016-01-15 16:13:28 +0800474 if (dobj->ops && dobj->ops->dai_unload)
475 dobj->ops->dai_unload(comp, dobj);
Liam Girdwood8a978232015-05-29 19:06:14 +0100476
477 list_del(&dobj->list);
Mengdong Lin64527e82016-01-15 16:13:28 +0800478 kfree(dai_drv);
Liam Girdwood8a978232015-05-29 19:06:14 +0100479}
480
Mengdong Linacfc7d42016-01-15 16:13:37 +0800481/* remove link configurations */
482static void remove_link(struct snd_soc_component *comp,
483 struct snd_soc_dobj *dobj, int pass)
484{
485 struct snd_soc_dai_link *link =
486 container_of(dobj, struct snd_soc_dai_link, dobj);
487
488 if (pass != SOC_TPLG_PASS_PCM_DAI)
489 return;
490
491 if (dobj->ops && dobj->ops->link_unload)
492 dobj->ops->link_unload(comp, dobj);
493
494 list_del(&dobj->list);
495 snd_soc_remove_dai_link(comp->card, link);
496 kfree(link);
497}
498
Liam Girdwood8a978232015-05-29 19:06:14 +0100499/* bind a kcontrol to it's IO handlers */
500static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr,
501 struct snd_kcontrol_new *k,
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800502 const struct soc_tplg *tplg)
Liam Girdwood8a978232015-05-29 19:06:14 +0100503{
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800504 const struct snd_soc_tplg_kcontrol_ops *ops;
Mengdong Lin1a3232d2015-08-18 18:12:20 +0800505 const struct snd_soc_tplg_bytes_ext_ops *ext_ops;
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800506 int num_ops, i;
Liam Girdwood8a978232015-05-29 19:06:14 +0100507
Mengdong Lin1a3232d2015-08-18 18:12:20 +0800508 if (hdr->ops.info == SND_SOC_TPLG_CTL_BYTES
509 && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER
510 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
511 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
512 struct soc_bytes_ext *sbe;
513 struct snd_soc_tplg_bytes_control *be;
514
515 sbe = (struct soc_bytes_ext *)k->private_value;
516 be = container_of(hdr, struct snd_soc_tplg_bytes_control, hdr);
517
518 /* TLV bytes controls need standard kcontrol info handler,
519 * TLV callback and extended put/get handlers.
520 */
Omair M Abdullahf4be9782015-11-09 23:20:01 +0530521 k->info = snd_soc_bytes_info_ext;
Mengdong Lin1a3232d2015-08-18 18:12:20 +0800522 k->tlv.c = snd_soc_bytes_tlv_callback;
523
524 ext_ops = tplg->bytes_ext_ops;
525 num_ops = tplg->bytes_ext_ops_count;
526 for (i = 0; i < num_ops; i++) {
527 if (!sbe->put && ext_ops[i].id == be->ext_ops.put)
528 sbe->put = ext_ops[i].put;
529 if (!sbe->get && ext_ops[i].id == be->ext_ops.get)
530 sbe->get = ext_ops[i].get;
531 }
532
533 if (sbe->put && sbe->get)
534 return 0;
535 else
536 return -EINVAL;
537 }
538
Mengdong Lin88a17d82015-08-18 18:11:51 +0800539 /* try and map vendor specific kcontrol handlers first */
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800540 ops = tplg->io_ops;
541 num_ops = tplg->io_ops_count;
Liam Girdwood8a978232015-05-29 19:06:14 +0100542 for (i = 0; i < num_ops; i++) {
543
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800544 if (k->put == NULL && ops[i].id == hdr->ops.put)
Liam Girdwood8a978232015-05-29 19:06:14 +0100545 k->put = ops[i].put;
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800546 if (k->get == NULL && ops[i].id == hdr->ops.get)
Liam Girdwood8a978232015-05-29 19:06:14 +0100547 k->get = ops[i].get;
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800548 if (k->info == NULL && ops[i].id == hdr->ops.info)
549 k->info = ops[i].info;
Liam Girdwood8a978232015-05-29 19:06:14 +0100550 }
551
Mengdong Lin88a17d82015-08-18 18:11:51 +0800552 /* vendor specific handlers found ? */
553 if (k->put && k->get && k->info)
554 return 0;
555
556 /* none found so try standard kcontrol handlers */
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800557 ops = io_ops;
558 num_ops = ARRAY_SIZE(io_ops);
Mengdong Lin88a17d82015-08-18 18:11:51 +0800559 for (i = 0; i < num_ops; i++) {
560
561 if (k->put == NULL && ops[i].id == hdr->ops.put)
562 k->put = ops[i].put;
563 if (k->get == NULL && ops[i].id == hdr->ops.get)
564 k->get = ops[i].get;
565 if (k->info == NULL && ops[i].id == hdr->ops.info)
Liam Girdwood8a978232015-05-29 19:06:14 +0100566 k->info = ops[i].info;
567 }
568
569 /* standard handlers found ? */
570 if (k->put && k->get && k->info)
571 return 0;
572
Liam Girdwood8a978232015-05-29 19:06:14 +0100573 /* nothing to bind */
574 return -EINVAL;
575}
576
577/* bind a widgets to it's evnt handlers */
578int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w,
579 const struct snd_soc_tplg_widget_events *events,
580 int num_events, u16 event_type)
581{
582 int i;
583
584 w->event = NULL;
585
586 for (i = 0; i < num_events; i++) {
587 if (event_type == events[i].type) {
588
589 /* found - so assign event */
590 w->event = events[i].event_handler;
591 return 0;
592 }
593 }
594
595 /* not found */
596 return -EINVAL;
597}
598EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_bind_event);
599
600/* optionally pass new dynamic kcontrol to component driver. */
601static int soc_tplg_init_kcontrol(struct soc_tplg *tplg,
602 struct snd_kcontrol_new *k, struct snd_soc_tplg_ctl_hdr *hdr)
603{
604 if (tplg->comp && tplg->ops && tplg->ops->control_load)
605 return tplg->ops->control_load(tplg->comp, k, hdr);
606
607 return 0;
608}
609
Mengdong Lin28a87ee2015-08-05 14:41:13 +0100610
611static int soc_tplg_create_tlv_db_scale(struct soc_tplg *tplg,
612 struct snd_kcontrol_new *kc, struct snd_soc_tplg_tlv_dbscale *scale)
Liam Girdwood8a978232015-05-29 19:06:14 +0100613{
Mengdong Lin28a87ee2015-08-05 14:41:13 +0100614 unsigned int item_len = 2 * sizeof(unsigned int);
615 unsigned int *p;
Liam Girdwood8a978232015-05-29 19:06:14 +0100616
Mengdong Lin28a87ee2015-08-05 14:41:13 +0100617 p = kzalloc(item_len + 2 * sizeof(unsigned int), GFP_KERNEL);
618 if (!p)
Liam Girdwood8a978232015-05-29 19:06:14 +0100619 return -ENOMEM;
620
Mengdong Lin28a87ee2015-08-05 14:41:13 +0100621 p[0] = SNDRV_CTL_TLVT_DB_SCALE;
622 p[1] = item_len;
623 p[2] = scale->min;
624 p[3] = (scale->step & TLV_DB_SCALE_MASK)
625 | (scale->mute ? TLV_DB_SCALE_MUTE : 0);
Liam Girdwood8a978232015-05-29 19:06:14 +0100626
Mengdong Lin28a87ee2015-08-05 14:41:13 +0100627 kc->tlv.p = (void *)p;
628 return 0;
629}
630
631static int soc_tplg_create_tlv(struct soc_tplg *tplg,
632 struct snd_kcontrol_new *kc, struct snd_soc_tplg_ctl_hdr *tc)
633{
634 struct snd_soc_tplg_ctl_tlv *tplg_tlv;
635
636 if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE))
637 return 0;
638
Mengdong Lin1a3232d2015-08-18 18:12:20 +0800639 if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {
Mengdong Lin28a87ee2015-08-05 14:41:13 +0100640 tplg_tlv = &tc->tlv;
641 switch (tplg_tlv->type) {
642 case SNDRV_CTL_TLVT_DB_SCALE:
643 return soc_tplg_create_tlv_db_scale(tplg, kc,
644 &tplg_tlv->scale);
645
646 /* TODO: add support for other TLV types */
647 default:
648 dev_dbg(tplg->dev, "Unsupported TLV type %d\n",
649 tplg_tlv->type);
650 return -EINVAL;
651 }
652 }
Liam Girdwood8a978232015-05-29 19:06:14 +0100653
654 return 0;
655}
656
657static inline void soc_tplg_free_tlv(struct soc_tplg *tplg,
658 struct snd_kcontrol_new *kc)
659{
660 kfree(kc->tlv.p);
661}
662
663static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count,
664 size_t size)
665{
666 struct snd_soc_tplg_bytes_control *be;
667 struct soc_bytes_ext *sbe;
668 struct snd_kcontrol_new kc;
669 int i, err;
670
671 if (soc_tplg_check_elem_count(tplg,
672 sizeof(struct snd_soc_tplg_bytes_control), count,
673 size, "mixer bytes")) {
674 dev_err(tplg->dev, "ASoC: Invalid count %d for byte control\n",
675 count);
676 return -EINVAL;
677 }
678
679 for (i = 0; i < count; i++) {
680 be = (struct snd_soc_tplg_bytes_control *)tplg->pos;
681
682 /* validate kcontrol */
683 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
684 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
685 return -EINVAL;
686
687 sbe = kzalloc(sizeof(*sbe), GFP_KERNEL);
688 if (sbe == NULL)
689 return -ENOMEM;
690
691 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) +
692 be->priv.size);
693
694 dev_dbg(tplg->dev,
695 "ASoC: adding bytes kcontrol %s with access 0x%x\n",
696 be->hdr.name, be->hdr.access);
697
698 memset(&kc, 0, sizeof(kc));
699 kc.name = be->hdr.name;
700 kc.private_value = (long)sbe;
701 kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
702 kc.access = be->hdr.access;
703
704 sbe->max = be->max;
705 sbe->dobj.type = SND_SOC_DOBJ_BYTES;
706 sbe->dobj.ops = tplg->ops;
707 INIT_LIST_HEAD(&sbe->dobj.list);
708
709 /* map io handlers */
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800710 err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, tplg);
Liam Girdwood8a978232015-05-29 19:06:14 +0100711 if (err) {
712 soc_control_err(tplg, &be->hdr, be->hdr.name);
713 kfree(sbe);
714 continue;
715 }
716
717 /* pass control to driver for optional further init */
718 err = soc_tplg_init_kcontrol(tplg, &kc,
719 (struct snd_soc_tplg_ctl_hdr *)be);
720 if (err < 0) {
721 dev_err(tplg->dev, "ASoC: failed to init %s\n",
722 be->hdr.name);
723 kfree(sbe);
724 continue;
725 }
726
727 /* register control here */
728 err = soc_tplg_add_kcontrol(tplg, &kc,
729 &sbe->dobj.control.kcontrol);
730 if (err < 0) {
731 dev_err(tplg->dev, "ASoC: failed to add %s\n",
732 be->hdr.name);
733 kfree(sbe);
734 continue;
735 }
736
737 list_add(&sbe->dobj.list, &tplg->comp->dobj_list);
738 }
739 return 0;
740
741}
742
743static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
744 size_t size)
745{
746 struct snd_soc_tplg_mixer_control *mc;
747 struct soc_mixer_control *sm;
748 struct snd_kcontrol_new kc;
749 int i, err;
750
751 if (soc_tplg_check_elem_count(tplg,
752 sizeof(struct snd_soc_tplg_mixer_control),
753 count, size, "mixers")) {
754
755 dev_err(tplg->dev, "ASoC: invalid count %d for controls\n",
756 count);
757 return -EINVAL;
758 }
759
760 for (i = 0; i < count; i++) {
761 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos;
762
763 /* validate kcontrol */
764 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
765 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
766 return -EINVAL;
767
768 sm = kzalloc(sizeof(*sm), GFP_KERNEL);
769 if (sm == NULL)
770 return -ENOMEM;
771 tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) +
772 mc->priv.size);
773
774 dev_dbg(tplg->dev,
775 "ASoC: adding mixer kcontrol %s with access 0x%x\n",
776 mc->hdr.name, mc->hdr.access);
777
778 memset(&kc, 0, sizeof(kc));
779 kc.name = mc->hdr.name;
780 kc.private_value = (long)sm;
781 kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
782 kc.access = mc->hdr.access;
783
784 /* we only support FL/FR channel mapping atm */
785 sm->reg = tplc_chan_get_reg(tplg, mc->channel,
786 SNDRV_CHMAP_FL);
787 sm->rreg = tplc_chan_get_reg(tplg, mc->channel,
788 SNDRV_CHMAP_FR);
789 sm->shift = tplc_chan_get_shift(tplg, mc->channel,
790 SNDRV_CHMAP_FL);
791 sm->rshift = tplc_chan_get_shift(tplg, mc->channel,
792 SNDRV_CHMAP_FR);
793
794 sm->max = mc->max;
795 sm->min = mc->min;
796 sm->invert = mc->invert;
797 sm->platform_max = mc->platform_max;
798 sm->dobj.index = tplg->index;
799 sm->dobj.ops = tplg->ops;
800 sm->dobj.type = SND_SOC_DOBJ_MIXER;
801 INIT_LIST_HEAD(&sm->dobj.list);
802
803 /* map io handlers */
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800804 err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, tplg);
Liam Girdwood8a978232015-05-29 19:06:14 +0100805 if (err) {
806 soc_control_err(tplg, &mc->hdr, mc->hdr.name);
807 kfree(sm);
808 continue;
809 }
810
811 /* pass control to driver for optional further init */
812 err = soc_tplg_init_kcontrol(tplg, &kc,
813 (struct snd_soc_tplg_ctl_hdr *) mc);
814 if (err < 0) {
815 dev_err(tplg->dev, "ASoC: failed to init %s\n",
816 mc->hdr.name);
817 kfree(sm);
818 continue;
819 }
820
821 /* create any TLV data */
Mengdong Lin28a87ee2015-08-05 14:41:13 +0100822 soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
Liam Girdwood8a978232015-05-29 19:06:14 +0100823
824 /* register control here */
825 err = soc_tplg_add_kcontrol(tplg, &kc,
826 &sm->dobj.control.kcontrol);
827 if (err < 0) {
828 dev_err(tplg->dev, "ASoC: failed to add %s\n",
829 mc->hdr.name);
830 soc_tplg_free_tlv(tplg, &kc);
831 kfree(sm);
832 continue;
833 }
834
835 list_add(&sm->dobj.list, &tplg->comp->dobj_list);
836 }
837
838 return 0;
839}
840
841static int soc_tplg_denum_create_texts(struct soc_enum *se,
842 struct snd_soc_tplg_enum_control *ec)
843{
844 int i, ret;
845
846 se->dobj.control.dtexts =
847 kzalloc(sizeof(char *) * ec->items, GFP_KERNEL);
848 if (se->dobj.control.dtexts == NULL)
849 return -ENOMEM;
850
851 for (i = 0; i < ec->items; i++) {
852
853 if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
854 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
855 ret = -EINVAL;
856 goto err;
857 }
858
859 se->dobj.control.dtexts[i] = kstrdup(ec->texts[i], GFP_KERNEL);
860 if (!se->dobj.control.dtexts[i]) {
861 ret = -ENOMEM;
862 goto err;
863 }
864 }
865
866 return 0;
867
868err:
869 for (--i; i >= 0; i--)
870 kfree(se->dobj.control.dtexts[i]);
871 kfree(se->dobj.control.dtexts);
872 return ret;
873}
874
875static int soc_tplg_denum_create_values(struct soc_enum *se,
876 struct snd_soc_tplg_enum_control *ec)
877{
878 if (ec->items > sizeof(*ec->values))
879 return -EINVAL;
880
Andrzej Hajda376c0af2015-08-07 09:59:37 +0200881 se->dobj.control.dvalues = kmemdup(ec->values,
882 ec->items * sizeof(u32),
883 GFP_KERNEL);
Liam Girdwood8a978232015-05-29 19:06:14 +0100884 if (!se->dobj.control.dvalues)
885 return -ENOMEM;
886
Liam Girdwood8a978232015-05-29 19:06:14 +0100887 return 0;
888}
889
890static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count,
891 size_t size)
892{
893 struct snd_soc_tplg_enum_control *ec;
894 struct soc_enum *se;
895 struct snd_kcontrol_new kc;
896 int i, ret, err;
897
898 if (soc_tplg_check_elem_count(tplg,
899 sizeof(struct snd_soc_tplg_enum_control),
900 count, size, "enums")) {
901
902 dev_err(tplg->dev, "ASoC: invalid count %d for enum controls\n",
903 count);
904 return -EINVAL;
905 }
906
907 for (i = 0; i < count; i++) {
908 ec = (struct snd_soc_tplg_enum_control *)tplg->pos;
909 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) +
910 ec->priv.size);
911
912 /* validate kcontrol */
913 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
914 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
915 return -EINVAL;
916
917 se = kzalloc((sizeof(*se)), GFP_KERNEL);
918 if (se == NULL)
919 return -ENOMEM;
920
921 dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n",
922 ec->hdr.name, ec->items);
923
924 memset(&kc, 0, sizeof(kc));
925 kc.name = ec->hdr.name;
926 kc.private_value = (long)se;
927 kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
928 kc.access = ec->hdr.access;
929
930 se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
931 se->shift_l = tplc_chan_get_shift(tplg, ec->channel,
932 SNDRV_CHMAP_FL);
933 se->shift_r = tplc_chan_get_shift(tplg, ec->channel,
934 SNDRV_CHMAP_FL);
935
936 se->items = ec->items;
937 se->mask = ec->mask;
938 se->dobj.index = tplg->index;
939 se->dobj.type = SND_SOC_DOBJ_ENUM;
940 se->dobj.ops = tplg->ops;
941 INIT_LIST_HEAD(&se->dobj.list);
942
943 switch (ec->hdr.ops.info) {
944 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
945 case SND_SOC_TPLG_CTL_ENUM_VALUE:
946 err = soc_tplg_denum_create_values(se, ec);
947 if (err < 0) {
948 dev_err(tplg->dev,
949 "ASoC: could not create values for %s\n",
950 ec->hdr.name);
951 kfree(se);
952 continue;
953 }
954 /* fall through and create texts */
955 case SND_SOC_TPLG_CTL_ENUM:
956 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
957 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
958 err = soc_tplg_denum_create_texts(se, ec);
959 if (err < 0) {
960 dev_err(tplg->dev,
961 "ASoC: could not create texts for %s\n",
962 ec->hdr.name);
963 kfree(se);
964 continue;
965 }
966 break;
967 default:
968 dev_err(tplg->dev,
969 "ASoC: invalid enum control type %d for %s\n",
970 ec->hdr.ops.info, ec->hdr.name);
971 kfree(se);
972 continue;
973 }
974
975 /* map io handlers */
Mengdong Lin2b5cdb92015-08-18 18:12:01 +0800976 err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg);
Liam Girdwood8a978232015-05-29 19:06:14 +0100977 if (err) {
978 soc_control_err(tplg, &ec->hdr, ec->hdr.name);
979 kfree(se);
980 continue;
981 }
982
983 /* pass control to driver for optional further init */
984 err = soc_tplg_init_kcontrol(tplg, &kc,
985 (struct snd_soc_tplg_ctl_hdr *) ec);
986 if (err < 0) {
987 dev_err(tplg->dev, "ASoC: failed to init %s\n",
988 ec->hdr.name);
989 kfree(se);
990 continue;
991 }
992
993 /* register control here */
994 ret = soc_tplg_add_kcontrol(tplg,
995 &kc, &se->dobj.control.kcontrol);
996 if (ret < 0) {
997 dev_err(tplg->dev, "ASoC: could not add kcontrol %s\n",
998 ec->hdr.name);
999 kfree(se);
1000 continue;
1001 }
1002
1003 list_add(&se->dobj.list, &tplg->comp->dobj_list);
1004 }
1005
1006 return 0;
1007}
1008
1009static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
1010 struct snd_soc_tplg_hdr *hdr)
1011{
1012 struct snd_soc_tplg_ctl_hdr *control_hdr;
1013 int i;
1014
1015 if (tplg->pass != SOC_TPLG_PASS_MIXER) {
1016 tplg->pos += hdr->size + hdr->payload_size;
1017 return 0;
1018 }
1019
1020 dev_dbg(tplg->dev, "ASoC: adding %d kcontrols at 0x%lx\n", hdr->count,
1021 soc_tplg_get_offset(tplg));
1022
1023 for (i = 0; i < hdr->count; i++) {
1024
1025 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
1026
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001027 if (control_hdr->size != sizeof(*control_hdr)) {
1028 dev_err(tplg->dev, "ASoC: invalid control size\n");
1029 return -EINVAL;
1030 }
1031
Liam Girdwood8a978232015-05-29 19:06:14 +01001032 switch (control_hdr->ops.info) {
1033 case SND_SOC_TPLG_CTL_VOLSW:
1034 case SND_SOC_TPLG_CTL_STROBE:
1035 case SND_SOC_TPLG_CTL_VOLSW_SX:
1036 case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
1037 case SND_SOC_TPLG_CTL_RANGE:
1038 case SND_SOC_TPLG_DAPM_CTL_VOLSW:
1039 case SND_SOC_TPLG_DAPM_CTL_PIN:
1040 soc_tplg_dmixer_create(tplg, 1, hdr->payload_size);
1041 break;
1042 case SND_SOC_TPLG_CTL_ENUM:
1043 case SND_SOC_TPLG_CTL_ENUM_VALUE:
1044 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
1045 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
1046 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
1047 soc_tplg_denum_create(tplg, 1, hdr->payload_size);
1048 break;
1049 case SND_SOC_TPLG_CTL_BYTES:
1050 soc_tplg_dbytes_create(tplg, 1, hdr->payload_size);
1051 break;
1052 default:
1053 soc_bind_err(tplg, control_hdr, i);
1054 return -EINVAL;
1055 }
1056 }
1057
1058 return 0;
1059}
1060
1061static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
1062 struct snd_soc_tplg_hdr *hdr)
1063{
1064 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;
1065 struct snd_soc_dapm_route route;
1066 struct snd_soc_tplg_dapm_graph_elem *elem;
1067 int count = hdr->count, i;
1068
1069 if (tplg->pass != SOC_TPLG_PASS_GRAPH) {
1070 tplg->pos += hdr->size + hdr->payload_size;
1071 return 0;
1072 }
1073
1074 if (soc_tplg_check_elem_count(tplg,
1075 sizeof(struct snd_soc_tplg_dapm_graph_elem),
1076 count, hdr->payload_size, "graph")) {
1077
1078 dev_err(tplg->dev, "ASoC: invalid count %d for DAPM routes\n",
1079 count);
1080 return -EINVAL;
1081 }
1082
1083 dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes\n", count);
1084
1085 for (i = 0; i < count; i++) {
1086 elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos;
1087 tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem);
1088
1089 /* validate routes */
1090 if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1091 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1092 return -EINVAL;
1093 if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1094 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1095 return -EINVAL;
1096 if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1097 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1098 return -EINVAL;
1099
1100 route.source = elem->source;
1101 route.sink = elem->sink;
1102 route.connected = NULL; /* set to NULL atm for tplg users */
1103 if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0)
1104 route.control = NULL;
1105 else
1106 route.control = elem->control;
1107
1108 /* add route, but keep going if some fail */
1109 snd_soc_dapm_add_routes(dapm, &route, 1);
1110 }
1111
1112 return 0;
1113}
1114
1115static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
1116 struct soc_tplg *tplg, int num_kcontrols)
1117{
1118 struct snd_kcontrol_new *kc;
1119 struct soc_mixer_control *sm;
1120 struct snd_soc_tplg_mixer_control *mc;
1121 int i, err;
1122
Axel Lin4ca7deb2015-08-05 22:34:22 +08001123 kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL);
Liam Girdwood8a978232015-05-29 19:06:14 +01001124 if (kc == NULL)
1125 return NULL;
1126
1127 for (i = 0; i < num_kcontrols; i++) {
1128 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos;
1129 sm = kzalloc(sizeof(*sm), GFP_KERNEL);
1130 if (sm == NULL)
1131 goto err;
1132
1133 tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) +
1134 mc->priv.size);
1135
1136 /* validate kcontrol */
1137 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1138 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1139 goto err_str;
1140
1141 dev_dbg(tplg->dev, " adding DAPM widget mixer control %s at %d\n",
1142 mc->hdr.name, i);
1143
1144 kc[i].name = mc->hdr.name;
1145 kc[i].private_value = (long)sm;
1146 kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1147 kc[i].access = mc->hdr.access;
1148
1149 /* we only support FL/FR channel mapping atm */
1150 sm->reg = tplc_chan_get_reg(tplg, mc->channel,
1151 SNDRV_CHMAP_FL);
1152 sm->rreg = tplc_chan_get_reg(tplg, mc->channel,
1153 SNDRV_CHMAP_FR);
1154 sm->shift = tplc_chan_get_shift(tplg, mc->channel,
1155 SNDRV_CHMAP_FL);
1156 sm->rshift = tplc_chan_get_shift(tplg, mc->channel,
1157 SNDRV_CHMAP_FR);
1158
1159 sm->max = mc->max;
1160 sm->min = mc->min;
1161 sm->invert = mc->invert;
1162 sm->platform_max = mc->platform_max;
1163 sm->dobj.index = tplg->index;
1164 INIT_LIST_HEAD(&sm->dobj.list);
1165
1166 /* map io handlers */
Mengdong Lin2b5cdb92015-08-18 18:12:01 +08001167 err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc[i], tplg);
Liam Girdwood8a978232015-05-29 19:06:14 +01001168 if (err) {
1169 soc_control_err(tplg, &mc->hdr, mc->hdr.name);
1170 kfree(sm);
1171 continue;
1172 }
1173
1174 /* pass control to driver for optional further init */
1175 err = soc_tplg_init_kcontrol(tplg, &kc[i],
1176 (struct snd_soc_tplg_ctl_hdr *)mc);
1177 if (err < 0) {
1178 dev_err(tplg->dev, "ASoC: failed to init %s\n",
1179 mc->hdr.name);
1180 kfree(sm);
1181 continue;
1182 }
Ranjani Sridharana74ae612018-03-09 11:11:17 -08001183
1184 /* create any TLV data */
1185 soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
Liam Girdwood8a978232015-05-29 19:06:14 +01001186 }
1187 return kc;
1188
1189err_str:
1190 kfree(sm);
1191err:
1192 for (--i; i >= 0; i--)
1193 kfree((void *)kc[i].private_value);
1194 kfree(kc);
1195 return NULL;
1196}
1197
1198static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create(
1199 struct soc_tplg *tplg)
1200{
1201 struct snd_kcontrol_new *kc;
1202 struct snd_soc_tplg_enum_control *ec;
1203 struct soc_enum *se;
1204 int i, err;
1205
1206 ec = (struct snd_soc_tplg_enum_control *)tplg->pos;
1207 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) +
1208 ec->priv.size);
1209
1210 /* validate kcontrol */
1211 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1212 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1213 return NULL;
1214
1215 kc = kzalloc(sizeof(*kc), GFP_KERNEL);
1216 if (kc == NULL)
1217 return NULL;
1218
1219 se = kzalloc(sizeof(*se), GFP_KERNEL);
1220 if (se == NULL)
1221 goto err;
1222
1223 dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n",
1224 ec->hdr.name);
1225
1226 kc->name = ec->hdr.name;
1227 kc->private_value = (long)se;
1228 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1229 kc->access = ec->hdr.access;
1230
1231 /* we only support FL/FR channel mapping atm */
1232 se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
1233 se->shift_l = tplc_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL);
1234 se->shift_r = tplc_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR);
1235
1236 se->items = ec->items;
1237 se->mask = ec->mask;
1238 se->dobj.index = tplg->index;
1239
1240 switch (ec->hdr.ops.info) {
1241 case SND_SOC_TPLG_CTL_ENUM_VALUE:
1242 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
1243 err = soc_tplg_denum_create_values(se, ec);
1244 if (err < 0) {
1245 dev_err(tplg->dev, "ASoC: could not create values for %s\n",
1246 ec->hdr.name);
1247 goto err_se;
1248 }
1249 /* fall through to create texts */
1250 case SND_SOC_TPLG_CTL_ENUM:
1251 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
1252 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
1253 err = soc_tplg_denum_create_texts(se, ec);
1254 if (err < 0) {
1255 dev_err(tplg->dev, "ASoC: could not create texts for %s\n",
1256 ec->hdr.name);
1257 goto err_se;
1258 }
1259 break;
1260 default:
1261 dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n",
1262 ec->hdr.ops.info, ec->hdr.name);
1263 goto err_se;
1264 }
1265
1266 /* map io handlers */
Mengdong Lin2b5cdb92015-08-18 18:12:01 +08001267 err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg);
Liam Girdwood8a978232015-05-29 19:06:14 +01001268 if (err) {
1269 soc_control_err(tplg, &ec->hdr, ec->hdr.name);
1270 goto err_se;
1271 }
1272
1273 /* pass control to driver for optional further init */
1274 err = soc_tplg_init_kcontrol(tplg, kc,
1275 (struct snd_soc_tplg_ctl_hdr *)ec);
1276 if (err < 0) {
1277 dev_err(tplg->dev, "ASoC: failed to init %s\n",
1278 ec->hdr.name);
1279 goto err_se;
1280 }
1281
1282 return kc;
1283
1284err_se:
1285 /* free values and texts */
1286 kfree(se->dobj.control.dvalues);
1287 for (i = 0; i < ec->items; i++)
1288 kfree(se->dobj.control.dtexts[i]);
1289
1290 kfree(se);
1291err:
1292 kfree(kc);
1293
1294 return NULL;
1295}
1296
1297static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create(
1298 struct soc_tplg *tplg, int count)
1299{
1300 struct snd_soc_tplg_bytes_control *be;
1301 struct soc_bytes_ext *sbe;
1302 struct snd_kcontrol_new *kc;
1303 int i, err;
1304
Axel Lin4ca7deb2015-08-05 22:34:22 +08001305 kc = kcalloc(count, sizeof(*kc), GFP_KERNEL);
Liam Girdwood8a978232015-05-29 19:06:14 +01001306 if (!kc)
1307 return NULL;
1308
1309 for (i = 0; i < count; i++) {
1310 be = (struct snd_soc_tplg_bytes_control *)tplg->pos;
1311
1312 /* validate kcontrol */
1313 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1314 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1315 goto err;
1316
1317 sbe = kzalloc(sizeof(*sbe), GFP_KERNEL);
1318 if (sbe == NULL)
1319 goto err;
1320
1321 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) +
1322 be->priv.size);
1323
1324 dev_dbg(tplg->dev,
1325 "ASoC: adding bytes kcontrol %s with access 0x%x\n",
1326 be->hdr.name, be->hdr.access);
1327
Liam Girdwood8a978232015-05-29 19:06:14 +01001328 kc[i].name = be->hdr.name;
1329 kc[i].private_value = (long)sbe;
1330 kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1331 kc[i].access = be->hdr.access;
1332
1333 sbe->max = be->max;
1334 INIT_LIST_HEAD(&sbe->dobj.list);
1335
1336 /* map standard io handlers and check for external handlers */
Mengdong Lin2b5cdb92015-08-18 18:12:01 +08001337 err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc[i], tplg);
Liam Girdwood8a978232015-05-29 19:06:14 +01001338 if (err) {
1339 soc_control_err(tplg, &be->hdr, be->hdr.name);
1340 kfree(sbe);
1341 continue;
1342 }
1343
1344 /* pass control to driver for optional further init */
1345 err = soc_tplg_init_kcontrol(tplg, &kc[i],
1346 (struct snd_soc_tplg_ctl_hdr *)be);
1347 if (err < 0) {
1348 dev_err(tplg->dev, "ASoC: failed to init %s\n",
1349 be->hdr.name);
1350 kfree(sbe);
1351 continue;
1352 }
1353 }
1354
1355 return kc;
1356
1357err:
1358 for (--i; i >= 0; i--)
1359 kfree((void *)kc[i].private_value);
1360
1361 kfree(kc);
1362 return NULL;
1363}
1364
1365static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg,
1366 struct snd_soc_tplg_dapm_widget *w)
1367{
1368 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;
1369 struct snd_soc_dapm_widget template, *widget;
1370 struct snd_soc_tplg_ctl_hdr *control_hdr;
1371 struct snd_soc_card *card = tplg->comp->card;
1372 int ret = 0;
1373
1374 if (strnlen(w->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1375 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1376 return -EINVAL;
1377 if (strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1378 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1379 return -EINVAL;
1380
1381 dev_dbg(tplg->dev, "ASoC: creating DAPM widget %s id %d\n",
1382 w->name, w->id);
1383
1384 memset(&template, 0, sizeof(template));
1385
1386 /* map user to kernel widget ID */
1387 template.id = get_widget_id(w->id);
1388 if (template.id < 0)
1389 return template.id;
1390
1391 template.name = kstrdup(w->name, GFP_KERNEL);
1392 if (!template.name)
1393 return -ENOMEM;
1394 template.sname = kstrdup(w->sname, GFP_KERNEL);
1395 if (!template.sname) {
1396 ret = -ENOMEM;
1397 goto err;
1398 }
1399 template.reg = w->reg;
1400 template.shift = w->shift;
1401 template.mask = w->mask;
Subhransu S. Prusty6dc6db72015-06-29 17:36:44 +01001402 template.subseq = w->subseq;
Liam Girdwood8a978232015-05-29 19:06:14 +01001403 template.on_val = w->invert ? 0 : 1;
1404 template.off_val = w->invert ? 1 : 0;
1405 template.ignore_suspend = w->ignore_suspend;
1406 template.event_flags = w->event_flags;
1407 template.dobj.index = tplg->index;
1408
1409 tplg->pos +=
1410 (sizeof(struct snd_soc_tplg_dapm_widget) + w->priv.size);
1411 if (w->num_kcontrols == 0) {
1412 template.num_kcontrols = 0;
1413 goto widget;
1414 }
1415
1416 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
1417 dev_dbg(tplg->dev, "ASoC: template %s has %d controls of type %x\n",
1418 w->name, w->num_kcontrols, control_hdr->type);
1419
1420 switch (control_hdr->ops.info) {
1421 case SND_SOC_TPLG_CTL_VOLSW:
1422 case SND_SOC_TPLG_CTL_STROBE:
1423 case SND_SOC_TPLG_CTL_VOLSW_SX:
1424 case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
1425 case SND_SOC_TPLG_CTL_RANGE:
1426 case SND_SOC_TPLG_DAPM_CTL_VOLSW:
1427 template.num_kcontrols = w->num_kcontrols;
1428 template.kcontrol_news =
1429 soc_tplg_dapm_widget_dmixer_create(tplg,
1430 template.num_kcontrols);
1431 if (!template.kcontrol_news) {
1432 ret = -ENOMEM;
1433 goto hdr_err;
1434 }
1435 break;
1436 case SND_SOC_TPLG_CTL_ENUM:
1437 case SND_SOC_TPLG_CTL_ENUM_VALUE:
1438 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
1439 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
1440 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
1441 template.dobj.widget.kcontrol_enum = 1;
1442 template.num_kcontrols = 1;
1443 template.kcontrol_news =
1444 soc_tplg_dapm_widget_denum_create(tplg);
1445 if (!template.kcontrol_news) {
1446 ret = -ENOMEM;
1447 goto hdr_err;
1448 }
1449 break;
1450 case SND_SOC_TPLG_CTL_BYTES:
1451 template.num_kcontrols = w->num_kcontrols;
1452 template.kcontrol_news =
1453 soc_tplg_dapm_widget_dbytes_create(tplg,
1454 template.num_kcontrols);
1455 if (!template.kcontrol_news) {
1456 ret = -ENOMEM;
1457 goto hdr_err;
1458 }
1459 break;
1460 default:
1461 dev_err(tplg->dev, "ASoC: invalid widget control type %d:%d:%d\n",
1462 control_hdr->ops.get, control_hdr->ops.put,
1463 control_hdr->ops.info);
1464 ret = -EINVAL;
1465 goto hdr_err;
1466 }
1467
1468widget:
1469 ret = soc_tplg_widget_load(tplg, &template, w);
1470 if (ret < 0)
1471 goto hdr_err;
1472
1473 /* card dapm mutex is held by the core if we are loading topology
1474 * data during sound card init. */
1475 if (card->instantiated)
1476 widget = snd_soc_dapm_new_control(dapm, &template);
1477 else
1478 widget = snd_soc_dapm_new_control_unlocked(dapm, &template);
Linus Walleijde415c82017-01-13 10:23:52 +01001479 if (IS_ERR(widget)) {
1480 ret = PTR_ERR(widget);
1481 /* Do not nag about probe deferrals */
1482 if (ret != -EPROBE_DEFER)
1483 dev_err(tplg->dev,
1484 "ASoC: failed to create widget %s controls (%d)\n",
1485 w->name, ret);
1486 goto hdr_err;
1487 }
Liam Girdwood8a978232015-05-29 19:06:14 +01001488 if (widget == NULL) {
1489 dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n",
1490 w->name);
Wei Yongjun8ae3ea42016-08-10 13:43:12 +00001491 ret = -ENOMEM;
Liam Girdwood8a978232015-05-29 19:06:14 +01001492 goto hdr_err;
1493 }
1494
1495 widget->dobj.type = SND_SOC_DOBJ_WIDGET;
1496 widget->dobj.ops = tplg->ops;
1497 widget->dobj.index = tplg->index;
Jeeja KP8ea41672016-05-05 11:19:18 +05301498 kfree(template.sname);
1499 kfree(template.name);
Liam Girdwood8a978232015-05-29 19:06:14 +01001500 list_add(&widget->dobj.list, &tplg->comp->dobj_list);
1501 return 0;
1502
1503hdr_err:
1504 kfree(template.sname);
1505err:
1506 kfree(template.name);
1507 return ret;
1508}
1509
1510static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg,
1511 struct snd_soc_tplg_hdr *hdr)
1512{
1513 struct snd_soc_tplg_dapm_widget *widget;
1514 int ret, count = hdr->count, i;
1515
1516 if (tplg->pass != SOC_TPLG_PASS_WIDGET)
1517 return 0;
1518
1519 dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count);
1520
1521 for (i = 0; i < count; i++) {
1522 widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001523 if (widget->size != sizeof(*widget)) {
1524 dev_err(tplg->dev, "ASoC: invalid widget size\n");
1525 return -EINVAL;
1526 }
1527
Liam Girdwood8a978232015-05-29 19:06:14 +01001528 ret = soc_tplg_dapm_widget_create(tplg, widget);
Mengdong Lin7de76b62016-04-27 14:52:38 +08001529 if (ret < 0) {
Liam Girdwood8a978232015-05-29 19:06:14 +01001530 dev_err(tplg->dev, "ASoC: failed to load widget %s\n",
1531 widget->name);
Mengdong Lin7de76b62016-04-27 14:52:38 +08001532 return ret;
1533 }
Liam Girdwood8a978232015-05-29 19:06:14 +01001534 }
1535
1536 return 0;
1537}
1538
1539static int soc_tplg_dapm_complete(struct soc_tplg *tplg)
1540{
1541 struct snd_soc_card *card = tplg->comp->card;
1542 int ret;
1543
1544 /* Card might not have been registered at this point.
1545 * If so, just return success.
1546 */
1547 if (!card || !card->instantiated) {
1548 dev_warn(tplg->dev, "ASoC: Parent card not yet available,"
1549 "Do not add new widgets now\n");
1550 return 0;
1551 }
1552
1553 ret = snd_soc_dapm_new_widgets(card);
1554 if (ret < 0)
1555 dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n",
1556 ret);
1557
1558 return 0;
1559}
1560
Mengdong Linb6b6e4d2016-02-22 16:29:19 +08001561static void set_stream_info(struct snd_soc_pcm_stream *stream,
1562 struct snd_soc_tplg_stream_caps *caps)
1563{
1564 stream->stream_name = kstrdup(caps->name, GFP_KERNEL);
1565 stream->channels_min = caps->channels_min;
1566 stream->channels_max = caps->channels_max;
1567 stream->rates = caps->rates;
1568 stream->rate_min = caps->rate_min;
1569 stream->rate_max = caps->rate_max;
1570 stream->formats = caps->formats;
Mengdong Linf918e162016-08-19 18:12:46 +08001571 stream->sig_bits = caps->sig_bits;
Mengdong Linb6b6e4d2016-02-22 16:29:19 +08001572}
1573
Mengdong Lin0038be92016-07-26 14:32:37 +08001574static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
1575 unsigned int flag_mask, unsigned int flags)
1576{
1577 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES)
1578 dai_drv->symmetric_rates =
1579 flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES ? 1 : 0;
1580
1581 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS)
1582 dai_drv->symmetric_channels =
1583 flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS ?
1584 1 : 0;
1585
1586 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS)
1587 dai_drv->symmetric_samplebits =
1588 flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS ?
1589 1 : 0;
1590}
1591
Mengdong Lin64527e82016-01-15 16:13:28 +08001592static int soc_tplg_dai_create(struct soc_tplg *tplg,
1593 struct snd_soc_tplg_pcm *pcm)
1594{
1595 struct snd_soc_dai_driver *dai_drv;
1596 struct snd_soc_pcm_stream *stream;
1597 struct snd_soc_tplg_stream_caps *caps;
1598 int ret;
1599
1600 dai_drv = kzalloc(sizeof(struct snd_soc_dai_driver), GFP_KERNEL);
1601 if (dai_drv == NULL)
1602 return -ENOMEM;
1603
1604 dai_drv->name = pcm->dai_name;
1605 dai_drv->id = pcm->dai_id;
1606
1607 if (pcm->playback) {
1608 stream = &dai_drv->playback;
1609 caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
Mengdong Linb6b6e4d2016-02-22 16:29:19 +08001610 set_stream_info(stream, caps);
Mengdong Lin64527e82016-01-15 16:13:28 +08001611 }
1612
1613 if (pcm->capture) {
1614 stream = &dai_drv->capture;
1615 caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE];
Mengdong Linb6b6e4d2016-02-22 16:29:19 +08001616 set_stream_info(stream, caps);
Mengdong Lin64527e82016-01-15 16:13:28 +08001617 }
1618
1619 /* pass control to component driver for optional further init */
1620 ret = soc_tplg_dai_load(tplg, dai_drv);
1621 if (ret < 0) {
1622 dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
1623 kfree(dai_drv);
1624 return ret;
1625 }
1626
1627 dai_drv->dobj.index = tplg->index;
1628 dai_drv->dobj.ops = tplg->ops;
1629 dai_drv->dobj.type = SND_SOC_DOBJ_PCM;
1630 list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list);
1631
1632 /* register the DAI to the component */
1633 return snd_soc_register_dai(tplg->comp, dai_drv);
1634}
1635
Guneshwor Singh67d1c212016-04-19 13:12:50 +08001636/* create the FE DAI link */
Mengdong Linacfc7d42016-01-15 16:13:37 +08001637static int soc_tplg_link_create(struct soc_tplg *tplg,
1638 struct snd_soc_tplg_pcm *pcm)
1639{
1640 struct snd_soc_dai_link *link;
1641 int ret;
1642
1643 link = kzalloc(sizeof(struct snd_soc_dai_link), GFP_KERNEL);
1644 if (link == NULL)
1645 return -ENOMEM;
1646
1647 link->name = pcm->pcm_name;
1648 link->stream_name = pcm->pcm_name;
Mengdong Linb84fff52016-04-19 13:12:43 +08001649 link->id = pcm->pcm_id;
Mengdong Linacfc7d42016-01-15 16:13:37 +08001650
Guneshwor Singh67d1c212016-04-19 13:12:50 +08001651 link->cpu_dai_name = pcm->dai_name;
1652 link->codec_name = "snd-soc-dummy";
1653 link->codec_dai_name = "snd-soc-dummy-dai";
1654
1655 /* enable DPCM */
1656 link->dynamic = 1;
1657 link->dpcm_playback = pcm->playback;
1658 link->dpcm_capture = pcm->capture;
1659
Mengdong Linacfc7d42016-01-15 16:13:37 +08001660 /* pass control to component driver for optional further init */
1661 ret = soc_tplg_dai_link_load(tplg, link);
1662 if (ret < 0) {
1663 dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n");
1664 kfree(link);
1665 return ret;
1666 }
1667
1668 link->dobj.index = tplg->index;
1669 link->dobj.ops = tplg->ops;
1670 link->dobj.type = SND_SOC_DOBJ_DAI_LINK;
1671 list_add(&link->dobj.list, &tplg->comp->dobj_list);
1672
1673 snd_soc_add_dai_link(tplg->comp->card, link);
1674 return 0;
1675}
1676
1677/* create a FE DAI and DAI link from the PCM object */
Mengdong Lin64527e82016-01-15 16:13:28 +08001678static int soc_tplg_pcm_create(struct soc_tplg *tplg,
1679 struct snd_soc_tplg_pcm *pcm)
1680{
Mengdong Linacfc7d42016-01-15 16:13:37 +08001681 int ret;
1682
1683 ret = soc_tplg_dai_create(tplg, pcm);
1684 if (ret < 0)
1685 return ret;
1686
1687 return soc_tplg_link_create(tplg, pcm);
Mengdong Lin64527e82016-01-15 16:13:28 +08001688}
1689
1690static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
Liam Girdwood8a978232015-05-29 19:06:14 +01001691 struct snd_soc_tplg_hdr *hdr)
1692{
Mengdong Lin64527e82016-01-15 16:13:28 +08001693 struct snd_soc_tplg_pcm *pcm;
Liam Girdwood8a978232015-05-29 19:06:14 +01001694 int count = hdr->count;
Mengdong Lin64527e82016-01-15 16:13:28 +08001695 int i;
Liam Girdwood8a978232015-05-29 19:06:14 +01001696
1697 if (tplg->pass != SOC_TPLG_PASS_PCM_DAI)
1698 return 0;
1699
Liam Girdwood8a978232015-05-29 19:06:14 +01001700 if (soc_tplg_check_elem_count(tplg,
Vedang Patel5b2688a2015-09-30 17:28:47 +08001701 sizeof(struct snd_soc_tplg_pcm), count,
Liam Girdwood8a978232015-05-29 19:06:14 +01001702 hdr->payload_size, "PCM DAI")) {
1703 dev_err(tplg->dev, "ASoC: invalid count %d for PCM DAI elems\n",
1704 count);
1705 return -EINVAL;
1706 }
1707
Mengdong Lin64527e82016-01-15 16:13:28 +08001708 /* create the FE DAIs and DAI links */
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001709 pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
Mengdong Lin64527e82016-01-15 16:13:28 +08001710 for (i = 0; i < count; i++) {
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001711 if (pcm->size != sizeof(*pcm)) {
1712 dev_err(tplg->dev, "ASoC: invalid pcm size\n");
1713 return -EINVAL;
1714 }
1715
Mengdong Lin64527e82016-01-15 16:13:28 +08001716 soc_tplg_pcm_create(tplg, pcm);
1717 pcm++;
1718 }
1719
Liam Girdwood8a978232015-05-29 19:06:14 +01001720 dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count);
Vedang Patel5b2688a2015-09-30 17:28:47 +08001721 tplg->pos += sizeof(struct snd_soc_tplg_pcm) * count;
Liam Girdwood8a978232015-05-29 19:06:14 +01001722
Liam Girdwood8a978232015-05-29 19:06:14 +01001723 return 0;
Liam Girdwood8a978232015-05-29 19:06:14 +01001724}
1725
Mengdong Lin0038be92016-07-26 14:32:37 +08001726/* *
1727 * soc_tplg_be_dai_config - Find and configure an existing BE DAI.
1728 * @tplg: topology context
1729 * @be: topology BE DAI configs.
1730 *
1731 * The BE dai should already be registered by the platform driver. The
1732 * platform driver should specify the BE DAI name and ID for matching.
1733 */
1734static int soc_tplg_be_dai_config(struct soc_tplg *tplg,
1735 struct snd_soc_tplg_be_dai *be)
1736{
1737 struct snd_soc_dai_link_component dai_component = {0};
1738 struct snd_soc_dai *dai;
1739 struct snd_soc_dai_driver *dai_drv;
1740 struct snd_soc_pcm_stream *stream;
1741 struct snd_soc_tplg_stream_caps *caps;
1742 int ret;
1743
1744 dai_component.dai_name = be->dai_name;
1745 dai = snd_soc_find_dai(&dai_component);
1746 if (!dai) {
1747 dev_err(tplg->dev, "ASoC: BE DAI %s not registered\n",
1748 be->dai_name);
1749 return -EINVAL;
1750 }
1751
1752 if (be->dai_id != dai->id) {
1753 dev_err(tplg->dev, "ASoC: BE DAI %s id mismatch\n",
1754 be->dai_name);
1755 return -EINVAL;
1756 }
1757
1758 dai_drv = dai->driver;
1759 if (!dai_drv)
1760 return -EINVAL;
1761
1762 if (be->playback) {
1763 stream = &dai_drv->playback;
1764 caps = &be->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
1765 set_stream_info(stream, caps);
1766 }
1767
1768 if (be->capture) {
1769 stream = &dai_drv->capture;
1770 caps = &be->caps[SND_SOC_TPLG_STREAM_CAPTURE];
1771 set_stream_info(stream, caps);
1772 }
1773
1774 if (be->flag_mask)
1775 set_dai_flags(dai_drv, be->flag_mask, be->flags);
1776
1777 /* pass control to component driver for optional further init */
1778 ret = soc_tplg_dai_load(tplg, dai_drv);
1779 if (ret < 0) {
1780 dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
1781 return ret;
1782 }
1783
1784 return 0;
1785}
1786
1787static int soc_tplg_be_dai_elems_load(struct soc_tplg *tplg,
1788 struct snd_soc_tplg_hdr *hdr)
1789{
1790 struct snd_soc_tplg_be_dai *be;
1791 int count = hdr->count;
1792 int i;
1793
1794 if (tplg->pass != SOC_TPLG_PASS_BE_DAI)
1795 return 0;
1796
1797 /* config the existing BE DAIs */
1798 for (i = 0; i < count; i++) {
1799 be = (struct snd_soc_tplg_be_dai *)tplg->pos;
1800 if (be->size != sizeof(*be)) {
1801 dev_err(tplg->dev, "ASoC: invalid BE DAI size\n");
1802 return -EINVAL;
1803 }
1804
1805 soc_tplg_be_dai_config(tplg, be);
1806 tplg->pos += (sizeof(*be) + be->priv.size);
1807 }
1808
1809 dev_dbg(tplg->dev, "ASoC: Configure %d BE DAIs\n", count);
1810 return 0;
1811}
1812
1813
Liam Girdwood8a978232015-05-29 19:06:14 +01001814static int soc_tplg_manifest_load(struct soc_tplg *tplg,
Mengdong Lin0038be92016-07-26 14:32:37 +08001815 struct snd_soc_tplg_hdr *hdr)
Liam Girdwood8a978232015-05-29 19:06:14 +01001816{
1817 struct snd_soc_tplg_manifest *manifest;
1818
1819 if (tplg->pass != SOC_TPLG_PASS_MANIFEST)
1820 return 0;
1821
1822 manifest = (struct snd_soc_tplg_manifest *)tplg->pos;
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001823 if (manifest->size != sizeof(*manifest)) {
1824 dev_err(tplg->dev, "ASoC: invalid manifest size\n");
1825 return -EINVAL;
1826 }
1827
Liam Girdwood8a978232015-05-29 19:06:14 +01001828 tplg->pos += sizeof(struct snd_soc_tplg_manifest);
1829
1830 if (tplg->comp && tplg->ops && tplg->ops->manifest)
1831 return tplg->ops->manifest(tplg->comp, manifest);
1832
1833 dev_err(tplg->dev, "ASoC: Firmware manifest not supported\n");
1834 return 0;
1835}
1836
1837/* validate header magic, size and type */
1838static int soc_valid_header(struct soc_tplg *tplg,
1839 struct snd_soc_tplg_hdr *hdr)
1840{
1841 if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size)
1842 return 0;
1843
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001844 if (hdr->size != sizeof(*hdr)) {
1845 dev_err(tplg->dev,
1846 "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n",
1847 hdr->type, soc_tplg_get_hdr_offset(tplg),
1848 tplg->fw->size);
1849 return -EINVAL;
1850 }
1851
Liam Girdwood8a978232015-05-29 19:06:14 +01001852 /* big endian firmware objects not supported atm */
1853 if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) {
1854 dev_err(tplg->dev,
1855 "ASoC: pass %d big endian not supported header got %x at offset 0x%lx size 0x%zx.\n",
1856 tplg->pass, hdr->magic,
1857 soc_tplg_get_hdr_offset(tplg), tplg->fw->size);
1858 return -EINVAL;
1859 }
1860
1861 if (hdr->magic != SND_SOC_TPLG_MAGIC) {
1862 dev_err(tplg->dev,
1863 "ASoC: pass %d does not have a valid header got %x at offset 0x%lx size 0x%zx.\n",
1864 tplg->pass, hdr->magic,
1865 soc_tplg_get_hdr_offset(tplg), tplg->fw->size);
1866 return -EINVAL;
1867 }
1868
1869 if (hdr->abi != SND_SOC_TPLG_ABI_VERSION) {
1870 dev_err(tplg->dev,
1871 "ASoC: pass %d invalid ABI version got 0x%x need 0x%x at offset 0x%lx size 0x%zx.\n",
1872 tplg->pass, hdr->abi,
1873 SND_SOC_TPLG_ABI_VERSION, soc_tplg_get_hdr_offset(tplg),
1874 tplg->fw->size);
1875 return -EINVAL;
1876 }
1877
1878 if (hdr->payload_size == 0) {
1879 dev_err(tplg->dev, "ASoC: header has 0 size at offset 0x%lx.\n",
1880 soc_tplg_get_hdr_offset(tplg));
1881 return -EINVAL;
1882 }
1883
1884 if (tplg->pass == hdr->type)
1885 dev_dbg(tplg->dev,
1886 "ASoC: Got 0x%x bytes of type %d version %d vendor %d at pass %d\n",
1887 hdr->payload_size, hdr->type, hdr->version,
1888 hdr->vendor_type, tplg->pass);
1889
1890 return 1;
1891}
1892
1893/* check header type and call appropriate handler */
1894static int soc_tplg_load_header(struct soc_tplg *tplg,
1895 struct snd_soc_tplg_hdr *hdr)
1896{
1897 tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr);
1898
1899 /* check for matching ID */
1900 if (hdr->index != tplg->req_index &&
1901 hdr->index != SND_SOC_TPLG_INDEX_ALL)
1902 return 0;
1903
1904 tplg->index = hdr->index;
1905
1906 switch (hdr->type) {
1907 case SND_SOC_TPLG_TYPE_MIXER:
1908 case SND_SOC_TPLG_TYPE_ENUM:
1909 case SND_SOC_TPLG_TYPE_BYTES:
1910 return soc_tplg_kcontrol_elems_load(tplg, hdr);
1911 case SND_SOC_TPLG_TYPE_DAPM_GRAPH:
1912 return soc_tplg_dapm_graph_elems_load(tplg, hdr);
1913 case SND_SOC_TPLG_TYPE_DAPM_WIDGET:
1914 return soc_tplg_dapm_widget_elems_load(tplg, hdr);
1915 case SND_SOC_TPLG_TYPE_PCM:
Mengdong Lin64527e82016-01-15 16:13:28 +08001916 return soc_tplg_pcm_elems_load(tplg, hdr);
Mengdong Lin0038be92016-07-26 14:32:37 +08001917 case SND_SOC_TPLG_TYPE_BE_DAI:
1918 return soc_tplg_be_dai_elems_load(tplg, hdr);
Liam Girdwood8a978232015-05-29 19:06:14 +01001919 case SND_SOC_TPLG_TYPE_MANIFEST:
1920 return soc_tplg_manifest_load(tplg, hdr);
1921 default:
1922 /* bespoke vendor data object */
1923 return soc_tplg_vendor_load(tplg, hdr);
1924 }
1925
1926 return 0;
1927}
1928
1929/* process the topology file headers */
1930static int soc_tplg_process_headers(struct soc_tplg *tplg)
1931{
1932 struct snd_soc_tplg_hdr *hdr;
1933 int ret;
1934
1935 tplg->pass = SOC_TPLG_PASS_START;
1936
1937 /* process the header types from start to end */
1938 while (tplg->pass <= SOC_TPLG_PASS_END) {
1939
1940 tplg->hdr_pos = tplg->fw->data;
1941 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;
1942
1943 while (!soc_tplg_is_eof(tplg)) {
1944
1945 /* make sure header is valid before loading */
1946 ret = soc_valid_header(tplg, hdr);
1947 if (ret < 0)
1948 return ret;
1949 else if (ret == 0)
1950 break;
1951
1952 /* load the header object */
1953 ret = soc_tplg_load_header(tplg, hdr);
1954 if (ret < 0)
1955 return ret;
1956
1957 /* goto next header */
1958 tplg->hdr_pos += hdr->payload_size +
1959 sizeof(struct snd_soc_tplg_hdr);
1960 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;
1961 }
1962
1963 /* next data type pass */
1964 tplg->pass++;
1965 }
1966
1967 /* signal DAPM we are complete */
1968 ret = soc_tplg_dapm_complete(tplg);
1969 if (ret < 0)
1970 dev_err(tplg->dev,
1971 "ASoC: failed to initialise DAPM from Firmware\n");
1972
1973 return ret;
1974}
1975
1976static int soc_tplg_load(struct soc_tplg *tplg)
1977{
1978 int ret;
1979
1980 ret = soc_tplg_process_headers(tplg);
1981 if (ret == 0)
1982 soc_tplg_complete(tplg);
1983
1984 return ret;
1985}
1986
1987/* load audio component topology from "firmware" file */
1988int snd_soc_tplg_component_load(struct snd_soc_component *comp,
1989 struct snd_soc_tplg_ops *ops, const struct firmware *fw, u32 id)
1990{
1991 struct soc_tplg tplg;
Bard liao5772f032019-02-17 21:23:47 +08001992 int ret;
Liam Girdwood8a978232015-05-29 19:06:14 +01001993
1994 /* setup parsing context */
1995 memset(&tplg, 0, sizeof(tplg));
1996 tplg.fw = fw;
1997 tplg.dev = comp->dev;
1998 tplg.comp = comp;
1999 tplg.ops = ops;
2000 tplg.req_index = id;
2001 tplg.io_ops = ops->io_ops;
2002 tplg.io_ops_count = ops->io_ops_count;
Mengdong Lin1a3232d2015-08-18 18:12:20 +08002003 tplg.bytes_ext_ops = ops->bytes_ext_ops;
2004 tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;
Liam Girdwood8a978232015-05-29 19:06:14 +01002005
Bard liao5772f032019-02-17 21:23:47 +08002006 ret = soc_tplg_load(&tplg);
2007 /* free the created components if fail to load topology */
2008 if (ret)
2009 snd_soc_tplg_component_remove(comp, SND_SOC_TPLG_INDEX_ALL);
2010
2011 return ret;
Liam Girdwood8a978232015-05-29 19:06:14 +01002012}
2013EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load);
2014
2015/* remove this dynamic widget */
2016void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget *w)
2017{
2018 /* make sure we are a widget */
2019 if (w->dobj.type != SND_SOC_DOBJ_WIDGET)
2020 return;
2021
2022 remove_widget(w->dapm->component, &w->dobj, SOC_TPLG_PASS_WIDGET);
2023}
2024EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove);
2025
2026/* remove all dynamic widgets from this DAPM context */
2027void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm,
2028 u32 index)
2029{
2030 struct snd_soc_dapm_widget *w, *next_w;
Liam Girdwood8a978232015-05-29 19:06:14 +01002031
2032 list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
2033
2034 /* make sure we are a widget with correct context */
2035 if (w->dobj.type != SND_SOC_DOBJ_WIDGET || w->dapm != dapm)
2036 continue;
2037
2038 /* match ID */
2039 if (w->dobj.index != index &&
2040 w->dobj.index != SND_SOC_TPLG_INDEX_ALL)
2041 continue;
Liam Girdwood8a978232015-05-29 19:06:14 +01002042 /* check and free and dynamic widget kcontrols */
2043 snd_soc_tplg_widget_remove(w);
Lars-Peter Clausenb97e2692015-07-21 18:11:07 +02002044 snd_soc_dapm_free_widget(w);
Liam Girdwood8a978232015-05-29 19:06:14 +01002045 }
Jyri Sarhafd589a12015-11-10 18:12:42 +02002046 snd_soc_dapm_reset_cache(dapm);
Liam Girdwood8a978232015-05-29 19:06:14 +01002047}
2048EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all);
2049
2050/* remove dynamic controls from the component driver */
2051int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index)
2052{
2053 struct snd_soc_dobj *dobj, *next_dobj;
2054 int pass = SOC_TPLG_PASS_END;
2055
2056 /* process the header types from end to start */
2057 while (pass >= SOC_TPLG_PASS_START) {
2058
2059 /* remove mixer controls */
2060 list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list,
2061 list) {
2062
2063 /* match index */
2064 if (dobj->index != index &&
2065 dobj->index != SND_SOC_TPLG_INDEX_ALL)
2066 continue;
2067
2068 switch (dobj->type) {
2069 case SND_SOC_DOBJ_MIXER:
2070 remove_mixer(comp, dobj, pass);
2071 break;
2072 case SND_SOC_DOBJ_ENUM:
2073 remove_enum(comp, dobj, pass);
2074 break;
2075 case SND_SOC_DOBJ_BYTES:
2076 remove_bytes(comp, dobj, pass);
2077 break;
2078 case SND_SOC_DOBJ_WIDGET:
2079 remove_widget(comp, dobj, pass);
2080 break;
2081 case SND_SOC_DOBJ_PCM:
Mengdong Lin64527e82016-01-15 16:13:28 +08002082 remove_dai(comp, dobj, pass);
Liam Girdwood8a978232015-05-29 19:06:14 +01002083 break;
Mengdong Linacfc7d42016-01-15 16:13:37 +08002084 case SND_SOC_DOBJ_DAI_LINK:
2085 remove_link(comp, dobj, pass);
2086 break;
Liam Girdwood8a978232015-05-29 19:06:14 +01002087 default:
2088 dev_err(comp->dev, "ASoC: invalid component type %d for removal\n",
2089 dobj->type);
2090 break;
2091 }
2092 }
2093 pass--;
2094 }
2095
2096 /* let caller know if FW can be freed when no objects are left */
2097 return !list_empty(&comp->dobj_list);
2098}
2099EXPORT_SYMBOL_GPL(snd_soc_tplg_component_remove);