blob: 6b05047a4134da76ff9abe96da16e5f6123d12aa [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 }
1183 }
1184 return kc;
1185
1186err_str:
1187 kfree(sm);
1188err:
1189 for (--i; i >= 0; i--)
1190 kfree((void *)kc[i].private_value);
1191 kfree(kc);
1192 return NULL;
1193}
1194
1195static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create(
1196 struct soc_tplg *tplg)
1197{
1198 struct snd_kcontrol_new *kc;
1199 struct snd_soc_tplg_enum_control *ec;
1200 struct soc_enum *se;
1201 int i, err;
1202
1203 ec = (struct snd_soc_tplg_enum_control *)tplg->pos;
1204 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) +
1205 ec->priv.size);
1206
1207 /* validate kcontrol */
1208 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1209 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1210 return NULL;
1211
1212 kc = kzalloc(sizeof(*kc), GFP_KERNEL);
1213 if (kc == NULL)
1214 return NULL;
1215
1216 se = kzalloc(sizeof(*se), GFP_KERNEL);
1217 if (se == NULL)
1218 goto err;
1219
1220 dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n",
1221 ec->hdr.name);
1222
1223 kc->name = ec->hdr.name;
1224 kc->private_value = (long)se;
1225 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1226 kc->access = ec->hdr.access;
1227
1228 /* we only support FL/FR channel mapping atm */
1229 se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
1230 se->shift_l = tplc_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL);
1231 se->shift_r = tplc_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR);
1232
1233 se->items = ec->items;
1234 se->mask = ec->mask;
1235 se->dobj.index = tplg->index;
1236
1237 switch (ec->hdr.ops.info) {
1238 case SND_SOC_TPLG_CTL_ENUM_VALUE:
1239 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
1240 err = soc_tplg_denum_create_values(se, ec);
1241 if (err < 0) {
1242 dev_err(tplg->dev, "ASoC: could not create values for %s\n",
1243 ec->hdr.name);
1244 goto err_se;
1245 }
1246 /* fall through to create texts */
1247 case SND_SOC_TPLG_CTL_ENUM:
1248 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
1249 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
1250 err = soc_tplg_denum_create_texts(se, ec);
1251 if (err < 0) {
1252 dev_err(tplg->dev, "ASoC: could not create texts for %s\n",
1253 ec->hdr.name);
1254 goto err_se;
1255 }
1256 break;
1257 default:
1258 dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n",
1259 ec->hdr.ops.info, ec->hdr.name);
1260 goto err_se;
1261 }
1262
1263 /* map io handlers */
Mengdong Lin2b5cdb92015-08-18 18:12:01 +08001264 err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg);
Liam Girdwood8a978232015-05-29 19:06:14 +01001265 if (err) {
1266 soc_control_err(tplg, &ec->hdr, ec->hdr.name);
1267 goto err_se;
1268 }
1269
1270 /* pass control to driver for optional further init */
1271 err = soc_tplg_init_kcontrol(tplg, kc,
1272 (struct snd_soc_tplg_ctl_hdr *)ec);
1273 if (err < 0) {
1274 dev_err(tplg->dev, "ASoC: failed to init %s\n",
1275 ec->hdr.name);
1276 goto err_se;
1277 }
1278
1279 return kc;
1280
1281err_se:
1282 /* free values and texts */
1283 kfree(se->dobj.control.dvalues);
1284 for (i = 0; i < ec->items; i++)
1285 kfree(se->dobj.control.dtexts[i]);
1286
1287 kfree(se);
1288err:
1289 kfree(kc);
1290
1291 return NULL;
1292}
1293
1294static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create(
1295 struct soc_tplg *tplg, int count)
1296{
1297 struct snd_soc_tplg_bytes_control *be;
1298 struct soc_bytes_ext *sbe;
1299 struct snd_kcontrol_new *kc;
1300 int i, err;
1301
Axel Lin4ca7deb2015-08-05 22:34:22 +08001302 kc = kcalloc(count, sizeof(*kc), GFP_KERNEL);
Liam Girdwood8a978232015-05-29 19:06:14 +01001303 if (!kc)
1304 return NULL;
1305
1306 for (i = 0; i < count; i++) {
1307 be = (struct snd_soc_tplg_bytes_control *)tplg->pos;
1308
1309 /* validate kcontrol */
1310 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1311 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1312 goto err;
1313
1314 sbe = kzalloc(sizeof(*sbe), GFP_KERNEL);
1315 if (sbe == NULL)
1316 goto err;
1317
1318 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) +
1319 be->priv.size);
1320
1321 dev_dbg(tplg->dev,
1322 "ASoC: adding bytes kcontrol %s with access 0x%x\n",
1323 be->hdr.name, be->hdr.access);
1324
Liam Girdwood8a978232015-05-29 19:06:14 +01001325 kc[i].name = be->hdr.name;
1326 kc[i].private_value = (long)sbe;
1327 kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1328 kc[i].access = be->hdr.access;
1329
1330 sbe->max = be->max;
1331 INIT_LIST_HEAD(&sbe->dobj.list);
1332
1333 /* map standard io handlers and check for external handlers */
Mengdong Lin2b5cdb92015-08-18 18:12:01 +08001334 err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc[i], tplg);
Liam Girdwood8a978232015-05-29 19:06:14 +01001335 if (err) {
1336 soc_control_err(tplg, &be->hdr, be->hdr.name);
1337 kfree(sbe);
1338 continue;
1339 }
1340
1341 /* pass control to driver for optional further init */
1342 err = soc_tplg_init_kcontrol(tplg, &kc[i],
1343 (struct snd_soc_tplg_ctl_hdr *)be);
1344 if (err < 0) {
1345 dev_err(tplg->dev, "ASoC: failed to init %s\n",
1346 be->hdr.name);
1347 kfree(sbe);
1348 continue;
1349 }
1350 }
1351
1352 return kc;
1353
1354err:
1355 for (--i; i >= 0; i--)
1356 kfree((void *)kc[i].private_value);
1357
1358 kfree(kc);
1359 return NULL;
1360}
1361
1362static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg,
1363 struct snd_soc_tplg_dapm_widget *w)
1364{
1365 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;
1366 struct snd_soc_dapm_widget template, *widget;
1367 struct snd_soc_tplg_ctl_hdr *control_hdr;
1368 struct snd_soc_card *card = tplg->comp->card;
1369 int ret = 0;
1370
1371 if (strnlen(w->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1372 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1373 return -EINVAL;
1374 if (strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1375 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1376 return -EINVAL;
1377
1378 dev_dbg(tplg->dev, "ASoC: creating DAPM widget %s id %d\n",
1379 w->name, w->id);
1380
1381 memset(&template, 0, sizeof(template));
1382
1383 /* map user to kernel widget ID */
1384 template.id = get_widget_id(w->id);
1385 if (template.id < 0)
1386 return template.id;
1387
1388 template.name = kstrdup(w->name, GFP_KERNEL);
1389 if (!template.name)
1390 return -ENOMEM;
1391 template.sname = kstrdup(w->sname, GFP_KERNEL);
1392 if (!template.sname) {
1393 ret = -ENOMEM;
1394 goto err;
1395 }
1396 template.reg = w->reg;
1397 template.shift = w->shift;
1398 template.mask = w->mask;
Subhransu S. Prusty6dc6db72015-06-29 17:36:44 +01001399 template.subseq = w->subseq;
Liam Girdwood8a978232015-05-29 19:06:14 +01001400 template.on_val = w->invert ? 0 : 1;
1401 template.off_val = w->invert ? 1 : 0;
1402 template.ignore_suspend = w->ignore_suspend;
1403 template.event_flags = w->event_flags;
1404 template.dobj.index = tplg->index;
1405
1406 tplg->pos +=
1407 (sizeof(struct snd_soc_tplg_dapm_widget) + w->priv.size);
1408 if (w->num_kcontrols == 0) {
1409 template.num_kcontrols = 0;
1410 goto widget;
1411 }
1412
1413 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
1414 dev_dbg(tplg->dev, "ASoC: template %s has %d controls of type %x\n",
1415 w->name, w->num_kcontrols, control_hdr->type);
1416
1417 switch (control_hdr->ops.info) {
1418 case SND_SOC_TPLG_CTL_VOLSW:
1419 case SND_SOC_TPLG_CTL_STROBE:
1420 case SND_SOC_TPLG_CTL_VOLSW_SX:
1421 case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
1422 case SND_SOC_TPLG_CTL_RANGE:
1423 case SND_SOC_TPLG_DAPM_CTL_VOLSW:
1424 template.num_kcontrols = w->num_kcontrols;
1425 template.kcontrol_news =
1426 soc_tplg_dapm_widget_dmixer_create(tplg,
1427 template.num_kcontrols);
1428 if (!template.kcontrol_news) {
1429 ret = -ENOMEM;
1430 goto hdr_err;
1431 }
1432 break;
1433 case SND_SOC_TPLG_CTL_ENUM:
1434 case SND_SOC_TPLG_CTL_ENUM_VALUE:
1435 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
1436 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
1437 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
1438 template.dobj.widget.kcontrol_enum = 1;
1439 template.num_kcontrols = 1;
1440 template.kcontrol_news =
1441 soc_tplg_dapm_widget_denum_create(tplg);
1442 if (!template.kcontrol_news) {
1443 ret = -ENOMEM;
1444 goto hdr_err;
1445 }
1446 break;
1447 case SND_SOC_TPLG_CTL_BYTES:
1448 template.num_kcontrols = w->num_kcontrols;
1449 template.kcontrol_news =
1450 soc_tplg_dapm_widget_dbytes_create(tplg,
1451 template.num_kcontrols);
1452 if (!template.kcontrol_news) {
1453 ret = -ENOMEM;
1454 goto hdr_err;
1455 }
1456 break;
1457 default:
1458 dev_err(tplg->dev, "ASoC: invalid widget control type %d:%d:%d\n",
1459 control_hdr->ops.get, control_hdr->ops.put,
1460 control_hdr->ops.info);
1461 ret = -EINVAL;
1462 goto hdr_err;
1463 }
1464
1465widget:
1466 ret = soc_tplg_widget_load(tplg, &template, w);
1467 if (ret < 0)
1468 goto hdr_err;
1469
1470 /* card dapm mutex is held by the core if we are loading topology
1471 * data during sound card init. */
1472 if (card->instantiated)
1473 widget = snd_soc_dapm_new_control(dapm, &template);
1474 else
1475 widget = snd_soc_dapm_new_control_unlocked(dapm, &template);
1476 if (widget == NULL) {
1477 dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n",
1478 w->name);
Wei Yongjun8ae3ea42016-08-10 13:43:12 +00001479 ret = -ENOMEM;
Liam Girdwood8a978232015-05-29 19:06:14 +01001480 goto hdr_err;
1481 }
1482
1483 widget->dobj.type = SND_SOC_DOBJ_WIDGET;
1484 widget->dobj.ops = tplg->ops;
1485 widget->dobj.index = tplg->index;
Jeeja KP8ea41672016-05-05 11:19:18 +05301486 kfree(template.sname);
1487 kfree(template.name);
Liam Girdwood8a978232015-05-29 19:06:14 +01001488 list_add(&widget->dobj.list, &tplg->comp->dobj_list);
1489 return 0;
1490
1491hdr_err:
1492 kfree(template.sname);
1493err:
1494 kfree(template.name);
1495 return ret;
1496}
1497
1498static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg,
1499 struct snd_soc_tplg_hdr *hdr)
1500{
1501 struct snd_soc_tplg_dapm_widget *widget;
1502 int ret, count = hdr->count, i;
1503
1504 if (tplg->pass != SOC_TPLG_PASS_WIDGET)
1505 return 0;
1506
1507 dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count);
1508
1509 for (i = 0; i < count; i++) {
1510 widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001511 if (widget->size != sizeof(*widget)) {
1512 dev_err(tplg->dev, "ASoC: invalid widget size\n");
1513 return -EINVAL;
1514 }
1515
Liam Girdwood8a978232015-05-29 19:06:14 +01001516 ret = soc_tplg_dapm_widget_create(tplg, widget);
Mengdong Lin7de76b62016-04-27 14:52:38 +08001517 if (ret < 0) {
Liam Girdwood8a978232015-05-29 19:06:14 +01001518 dev_err(tplg->dev, "ASoC: failed to load widget %s\n",
1519 widget->name);
Mengdong Lin7de76b62016-04-27 14:52:38 +08001520 return ret;
1521 }
Liam Girdwood8a978232015-05-29 19:06:14 +01001522 }
1523
1524 return 0;
1525}
1526
1527static int soc_tplg_dapm_complete(struct soc_tplg *tplg)
1528{
1529 struct snd_soc_card *card = tplg->comp->card;
1530 int ret;
1531
1532 /* Card might not have been registered at this point.
1533 * If so, just return success.
1534 */
1535 if (!card || !card->instantiated) {
1536 dev_warn(tplg->dev, "ASoC: Parent card not yet available,"
1537 "Do not add new widgets now\n");
1538 return 0;
1539 }
1540
1541 ret = snd_soc_dapm_new_widgets(card);
1542 if (ret < 0)
1543 dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n",
1544 ret);
1545
1546 return 0;
1547}
1548
Mengdong Linb6b6e4d2016-02-22 16:29:19 +08001549static void set_stream_info(struct snd_soc_pcm_stream *stream,
1550 struct snd_soc_tplg_stream_caps *caps)
1551{
1552 stream->stream_name = kstrdup(caps->name, GFP_KERNEL);
1553 stream->channels_min = caps->channels_min;
1554 stream->channels_max = caps->channels_max;
1555 stream->rates = caps->rates;
1556 stream->rate_min = caps->rate_min;
1557 stream->rate_max = caps->rate_max;
1558 stream->formats = caps->formats;
Mengdong Linf918e162016-08-19 18:12:46 +08001559 stream->sig_bits = caps->sig_bits;
Mengdong Linb6b6e4d2016-02-22 16:29:19 +08001560}
1561
Mengdong Lin0038be92016-07-26 14:32:37 +08001562static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
1563 unsigned int flag_mask, unsigned int flags)
1564{
1565 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES)
1566 dai_drv->symmetric_rates =
1567 flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES ? 1 : 0;
1568
1569 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS)
1570 dai_drv->symmetric_channels =
1571 flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS ?
1572 1 : 0;
1573
1574 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS)
1575 dai_drv->symmetric_samplebits =
1576 flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS ?
1577 1 : 0;
1578}
1579
Mengdong Lin64527e82016-01-15 16:13:28 +08001580static int soc_tplg_dai_create(struct soc_tplg *tplg,
1581 struct snd_soc_tplg_pcm *pcm)
1582{
1583 struct snd_soc_dai_driver *dai_drv;
1584 struct snd_soc_pcm_stream *stream;
1585 struct snd_soc_tplg_stream_caps *caps;
1586 int ret;
1587
1588 dai_drv = kzalloc(sizeof(struct snd_soc_dai_driver), GFP_KERNEL);
1589 if (dai_drv == NULL)
1590 return -ENOMEM;
1591
1592 dai_drv->name = pcm->dai_name;
1593 dai_drv->id = pcm->dai_id;
1594
1595 if (pcm->playback) {
1596 stream = &dai_drv->playback;
1597 caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
Mengdong Linb6b6e4d2016-02-22 16:29:19 +08001598 set_stream_info(stream, caps);
Mengdong Lin64527e82016-01-15 16:13:28 +08001599 }
1600
1601 if (pcm->capture) {
1602 stream = &dai_drv->capture;
1603 caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE];
Mengdong Linb6b6e4d2016-02-22 16:29:19 +08001604 set_stream_info(stream, caps);
Mengdong Lin64527e82016-01-15 16:13:28 +08001605 }
1606
1607 /* pass control to component driver for optional further init */
1608 ret = soc_tplg_dai_load(tplg, dai_drv);
1609 if (ret < 0) {
1610 dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
1611 kfree(dai_drv);
1612 return ret;
1613 }
1614
1615 dai_drv->dobj.index = tplg->index;
1616 dai_drv->dobj.ops = tplg->ops;
1617 dai_drv->dobj.type = SND_SOC_DOBJ_PCM;
1618 list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list);
1619
1620 /* register the DAI to the component */
1621 return snd_soc_register_dai(tplg->comp, dai_drv);
1622}
1623
Guneshwor Singh67d1c212016-04-19 13:12:50 +08001624/* create the FE DAI link */
Mengdong Linacfc7d42016-01-15 16:13:37 +08001625static int soc_tplg_link_create(struct soc_tplg *tplg,
1626 struct snd_soc_tplg_pcm *pcm)
1627{
1628 struct snd_soc_dai_link *link;
1629 int ret;
1630
1631 link = kzalloc(sizeof(struct snd_soc_dai_link), GFP_KERNEL);
1632 if (link == NULL)
1633 return -ENOMEM;
1634
1635 link->name = pcm->pcm_name;
1636 link->stream_name = pcm->pcm_name;
Mengdong Linb84fff52016-04-19 13:12:43 +08001637 link->id = pcm->pcm_id;
Mengdong Linacfc7d42016-01-15 16:13:37 +08001638
Guneshwor Singh67d1c212016-04-19 13:12:50 +08001639 link->cpu_dai_name = pcm->dai_name;
1640 link->codec_name = "snd-soc-dummy";
1641 link->codec_dai_name = "snd-soc-dummy-dai";
1642
1643 /* enable DPCM */
1644 link->dynamic = 1;
1645 link->dpcm_playback = pcm->playback;
1646 link->dpcm_capture = pcm->capture;
1647
Mengdong Linacfc7d42016-01-15 16:13:37 +08001648 /* pass control to component driver for optional further init */
1649 ret = soc_tplg_dai_link_load(tplg, link);
1650 if (ret < 0) {
1651 dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n");
1652 kfree(link);
1653 return ret;
1654 }
1655
1656 link->dobj.index = tplg->index;
1657 link->dobj.ops = tplg->ops;
1658 link->dobj.type = SND_SOC_DOBJ_DAI_LINK;
1659 list_add(&link->dobj.list, &tplg->comp->dobj_list);
1660
1661 snd_soc_add_dai_link(tplg->comp->card, link);
1662 return 0;
1663}
1664
1665/* create a FE DAI and DAI link from the PCM object */
Mengdong Lin64527e82016-01-15 16:13:28 +08001666static int soc_tplg_pcm_create(struct soc_tplg *tplg,
1667 struct snd_soc_tplg_pcm *pcm)
1668{
Mengdong Linacfc7d42016-01-15 16:13:37 +08001669 int ret;
1670
1671 ret = soc_tplg_dai_create(tplg, pcm);
1672 if (ret < 0)
1673 return ret;
1674
1675 return soc_tplg_link_create(tplg, pcm);
Mengdong Lin64527e82016-01-15 16:13:28 +08001676}
1677
1678static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
Liam Girdwood8a978232015-05-29 19:06:14 +01001679 struct snd_soc_tplg_hdr *hdr)
1680{
Mengdong Lin64527e82016-01-15 16:13:28 +08001681 struct snd_soc_tplg_pcm *pcm;
Liam Girdwood8a978232015-05-29 19:06:14 +01001682 int count = hdr->count;
Mengdong Lin64527e82016-01-15 16:13:28 +08001683 int i;
Liam Girdwood8a978232015-05-29 19:06:14 +01001684
1685 if (tplg->pass != SOC_TPLG_PASS_PCM_DAI)
1686 return 0;
1687
Liam Girdwood8a978232015-05-29 19:06:14 +01001688 if (soc_tplg_check_elem_count(tplg,
Vedang Patel5b2688a2015-09-30 17:28:47 +08001689 sizeof(struct snd_soc_tplg_pcm), count,
Liam Girdwood8a978232015-05-29 19:06:14 +01001690 hdr->payload_size, "PCM DAI")) {
1691 dev_err(tplg->dev, "ASoC: invalid count %d for PCM DAI elems\n",
1692 count);
1693 return -EINVAL;
1694 }
1695
Mengdong Lin64527e82016-01-15 16:13:28 +08001696 /* create the FE DAIs and DAI links */
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001697 pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
Mengdong Lin64527e82016-01-15 16:13:28 +08001698 for (i = 0; i < count; i++) {
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001699 if (pcm->size != sizeof(*pcm)) {
1700 dev_err(tplg->dev, "ASoC: invalid pcm size\n");
1701 return -EINVAL;
1702 }
1703
Mengdong Lin64527e82016-01-15 16:13:28 +08001704 soc_tplg_pcm_create(tplg, pcm);
1705 pcm++;
1706 }
1707
Liam Girdwood8a978232015-05-29 19:06:14 +01001708 dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count);
Vedang Patel5b2688a2015-09-30 17:28:47 +08001709 tplg->pos += sizeof(struct snd_soc_tplg_pcm) * count;
Liam Girdwood8a978232015-05-29 19:06:14 +01001710
Liam Girdwood8a978232015-05-29 19:06:14 +01001711 return 0;
Liam Girdwood8a978232015-05-29 19:06:14 +01001712}
1713
Mengdong Lin0038be92016-07-26 14:32:37 +08001714/* *
1715 * soc_tplg_be_dai_config - Find and configure an existing BE DAI.
1716 * @tplg: topology context
1717 * @be: topology BE DAI configs.
1718 *
1719 * The BE dai should already be registered by the platform driver. The
1720 * platform driver should specify the BE DAI name and ID for matching.
1721 */
1722static int soc_tplg_be_dai_config(struct soc_tplg *tplg,
1723 struct snd_soc_tplg_be_dai *be)
1724{
1725 struct snd_soc_dai_link_component dai_component = {0};
1726 struct snd_soc_dai *dai;
1727 struct snd_soc_dai_driver *dai_drv;
1728 struct snd_soc_pcm_stream *stream;
1729 struct snd_soc_tplg_stream_caps *caps;
1730 int ret;
1731
1732 dai_component.dai_name = be->dai_name;
1733 dai = snd_soc_find_dai(&dai_component);
1734 if (!dai) {
1735 dev_err(tplg->dev, "ASoC: BE DAI %s not registered\n",
1736 be->dai_name);
1737 return -EINVAL;
1738 }
1739
1740 if (be->dai_id != dai->id) {
1741 dev_err(tplg->dev, "ASoC: BE DAI %s id mismatch\n",
1742 be->dai_name);
1743 return -EINVAL;
1744 }
1745
1746 dai_drv = dai->driver;
1747 if (!dai_drv)
1748 return -EINVAL;
1749
1750 if (be->playback) {
1751 stream = &dai_drv->playback;
1752 caps = &be->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
1753 set_stream_info(stream, caps);
1754 }
1755
1756 if (be->capture) {
1757 stream = &dai_drv->capture;
1758 caps = &be->caps[SND_SOC_TPLG_STREAM_CAPTURE];
1759 set_stream_info(stream, caps);
1760 }
1761
1762 if (be->flag_mask)
1763 set_dai_flags(dai_drv, be->flag_mask, be->flags);
1764
1765 /* pass control to component driver for optional further init */
1766 ret = soc_tplg_dai_load(tplg, dai_drv);
1767 if (ret < 0) {
1768 dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
1769 return ret;
1770 }
1771
1772 return 0;
1773}
1774
1775static int soc_tplg_be_dai_elems_load(struct soc_tplg *tplg,
1776 struct snd_soc_tplg_hdr *hdr)
1777{
1778 struct snd_soc_tplg_be_dai *be;
1779 int count = hdr->count;
1780 int i;
1781
1782 if (tplg->pass != SOC_TPLG_PASS_BE_DAI)
1783 return 0;
1784
1785 /* config the existing BE DAIs */
1786 for (i = 0; i < count; i++) {
1787 be = (struct snd_soc_tplg_be_dai *)tplg->pos;
1788 if (be->size != sizeof(*be)) {
1789 dev_err(tplg->dev, "ASoC: invalid BE DAI size\n");
1790 return -EINVAL;
1791 }
1792
1793 soc_tplg_be_dai_config(tplg, be);
1794 tplg->pos += (sizeof(*be) + be->priv.size);
1795 }
1796
1797 dev_dbg(tplg->dev, "ASoC: Configure %d BE DAIs\n", count);
1798 return 0;
1799}
1800
1801
Liam Girdwood8a978232015-05-29 19:06:14 +01001802static int soc_tplg_manifest_load(struct soc_tplg *tplg,
Mengdong Lin0038be92016-07-26 14:32:37 +08001803 struct snd_soc_tplg_hdr *hdr)
Liam Girdwood8a978232015-05-29 19:06:14 +01001804{
1805 struct snd_soc_tplg_manifest *manifest;
1806
1807 if (tplg->pass != SOC_TPLG_PASS_MANIFEST)
1808 return 0;
1809
1810 manifest = (struct snd_soc_tplg_manifest *)tplg->pos;
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001811 if (manifest->size != sizeof(*manifest)) {
1812 dev_err(tplg->dev, "ASoC: invalid manifest size\n");
1813 return -EINVAL;
1814 }
1815
Liam Girdwood8a978232015-05-29 19:06:14 +01001816 tplg->pos += sizeof(struct snd_soc_tplg_manifest);
1817
1818 if (tplg->comp && tplg->ops && tplg->ops->manifest)
1819 return tplg->ops->manifest(tplg->comp, manifest);
1820
1821 dev_err(tplg->dev, "ASoC: Firmware manifest not supported\n");
1822 return 0;
1823}
1824
1825/* validate header magic, size and type */
1826static int soc_valid_header(struct soc_tplg *tplg,
1827 struct snd_soc_tplg_hdr *hdr)
1828{
1829 if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size)
1830 return 0;
1831
Mengdong Lin06eb49f2016-04-27 14:52:56 +08001832 if (hdr->size != sizeof(*hdr)) {
1833 dev_err(tplg->dev,
1834 "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n",
1835 hdr->type, soc_tplg_get_hdr_offset(tplg),
1836 tplg->fw->size);
1837 return -EINVAL;
1838 }
1839
Liam Girdwood8a978232015-05-29 19:06:14 +01001840 /* big endian firmware objects not supported atm */
1841 if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) {
1842 dev_err(tplg->dev,
1843 "ASoC: pass %d big endian not supported header got %x at offset 0x%lx size 0x%zx.\n",
1844 tplg->pass, hdr->magic,
1845 soc_tplg_get_hdr_offset(tplg), tplg->fw->size);
1846 return -EINVAL;
1847 }
1848
1849 if (hdr->magic != SND_SOC_TPLG_MAGIC) {
1850 dev_err(tplg->dev,
1851 "ASoC: pass %d does not have a valid header got %x at offset 0x%lx size 0x%zx.\n",
1852 tplg->pass, hdr->magic,
1853 soc_tplg_get_hdr_offset(tplg), tplg->fw->size);
1854 return -EINVAL;
1855 }
1856
1857 if (hdr->abi != SND_SOC_TPLG_ABI_VERSION) {
1858 dev_err(tplg->dev,
1859 "ASoC: pass %d invalid ABI version got 0x%x need 0x%x at offset 0x%lx size 0x%zx.\n",
1860 tplg->pass, hdr->abi,
1861 SND_SOC_TPLG_ABI_VERSION, soc_tplg_get_hdr_offset(tplg),
1862 tplg->fw->size);
1863 return -EINVAL;
1864 }
1865
1866 if (hdr->payload_size == 0) {
1867 dev_err(tplg->dev, "ASoC: header has 0 size at offset 0x%lx.\n",
1868 soc_tplg_get_hdr_offset(tplg));
1869 return -EINVAL;
1870 }
1871
1872 if (tplg->pass == hdr->type)
1873 dev_dbg(tplg->dev,
1874 "ASoC: Got 0x%x bytes of type %d version %d vendor %d at pass %d\n",
1875 hdr->payload_size, hdr->type, hdr->version,
1876 hdr->vendor_type, tplg->pass);
1877
1878 return 1;
1879}
1880
1881/* check header type and call appropriate handler */
1882static int soc_tplg_load_header(struct soc_tplg *tplg,
1883 struct snd_soc_tplg_hdr *hdr)
1884{
1885 tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr);
1886
1887 /* check for matching ID */
1888 if (hdr->index != tplg->req_index &&
1889 hdr->index != SND_SOC_TPLG_INDEX_ALL)
1890 return 0;
1891
1892 tplg->index = hdr->index;
1893
1894 switch (hdr->type) {
1895 case SND_SOC_TPLG_TYPE_MIXER:
1896 case SND_SOC_TPLG_TYPE_ENUM:
1897 case SND_SOC_TPLG_TYPE_BYTES:
1898 return soc_tplg_kcontrol_elems_load(tplg, hdr);
1899 case SND_SOC_TPLG_TYPE_DAPM_GRAPH:
1900 return soc_tplg_dapm_graph_elems_load(tplg, hdr);
1901 case SND_SOC_TPLG_TYPE_DAPM_WIDGET:
1902 return soc_tplg_dapm_widget_elems_load(tplg, hdr);
1903 case SND_SOC_TPLG_TYPE_PCM:
Mengdong Lin64527e82016-01-15 16:13:28 +08001904 return soc_tplg_pcm_elems_load(tplg, hdr);
Mengdong Lin0038be92016-07-26 14:32:37 +08001905 case SND_SOC_TPLG_TYPE_BE_DAI:
1906 return soc_tplg_be_dai_elems_load(tplg, hdr);
Liam Girdwood8a978232015-05-29 19:06:14 +01001907 case SND_SOC_TPLG_TYPE_MANIFEST:
1908 return soc_tplg_manifest_load(tplg, hdr);
1909 default:
1910 /* bespoke vendor data object */
1911 return soc_tplg_vendor_load(tplg, hdr);
1912 }
1913
1914 return 0;
1915}
1916
1917/* process the topology file headers */
1918static int soc_tplg_process_headers(struct soc_tplg *tplg)
1919{
1920 struct snd_soc_tplg_hdr *hdr;
1921 int ret;
1922
1923 tplg->pass = SOC_TPLG_PASS_START;
1924
1925 /* process the header types from start to end */
1926 while (tplg->pass <= SOC_TPLG_PASS_END) {
1927
1928 tplg->hdr_pos = tplg->fw->data;
1929 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;
1930
1931 while (!soc_tplg_is_eof(tplg)) {
1932
1933 /* make sure header is valid before loading */
1934 ret = soc_valid_header(tplg, hdr);
1935 if (ret < 0)
1936 return ret;
1937 else if (ret == 0)
1938 break;
1939
1940 /* load the header object */
1941 ret = soc_tplg_load_header(tplg, hdr);
1942 if (ret < 0)
1943 return ret;
1944
1945 /* goto next header */
1946 tplg->hdr_pos += hdr->payload_size +
1947 sizeof(struct snd_soc_tplg_hdr);
1948 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;
1949 }
1950
1951 /* next data type pass */
1952 tplg->pass++;
1953 }
1954
1955 /* signal DAPM we are complete */
1956 ret = soc_tplg_dapm_complete(tplg);
1957 if (ret < 0)
1958 dev_err(tplg->dev,
1959 "ASoC: failed to initialise DAPM from Firmware\n");
1960
1961 return ret;
1962}
1963
1964static int soc_tplg_load(struct soc_tplg *tplg)
1965{
1966 int ret;
1967
1968 ret = soc_tplg_process_headers(tplg);
1969 if (ret == 0)
1970 soc_tplg_complete(tplg);
1971
1972 return ret;
1973}
1974
1975/* load audio component topology from "firmware" file */
1976int snd_soc_tplg_component_load(struct snd_soc_component *comp,
1977 struct snd_soc_tplg_ops *ops, const struct firmware *fw, u32 id)
1978{
1979 struct soc_tplg tplg;
1980
1981 /* setup parsing context */
1982 memset(&tplg, 0, sizeof(tplg));
1983 tplg.fw = fw;
1984 tplg.dev = comp->dev;
1985 tplg.comp = comp;
1986 tplg.ops = ops;
1987 tplg.req_index = id;
1988 tplg.io_ops = ops->io_ops;
1989 tplg.io_ops_count = ops->io_ops_count;
Mengdong Lin1a3232d2015-08-18 18:12:20 +08001990 tplg.bytes_ext_ops = ops->bytes_ext_ops;
1991 tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;
Liam Girdwood8a978232015-05-29 19:06:14 +01001992
1993 return soc_tplg_load(&tplg);
1994}
1995EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load);
1996
1997/* remove this dynamic widget */
1998void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget *w)
1999{
2000 /* make sure we are a widget */
2001 if (w->dobj.type != SND_SOC_DOBJ_WIDGET)
2002 return;
2003
2004 remove_widget(w->dapm->component, &w->dobj, SOC_TPLG_PASS_WIDGET);
2005}
2006EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove);
2007
2008/* remove all dynamic widgets from this DAPM context */
2009void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm,
2010 u32 index)
2011{
2012 struct snd_soc_dapm_widget *w, *next_w;
Liam Girdwood8a978232015-05-29 19:06:14 +01002013
2014 list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
2015
2016 /* make sure we are a widget with correct context */
2017 if (w->dobj.type != SND_SOC_DOBJ_WIDGET || w->dapm != dapm)
2018 continue;
2019
2020 /* match ID */
2021 if (w->dobj.index != index &&
2022 w->dobj.index != SND_SOC_TPLG_INDEX_ALL)
2023 continue;
Liam Girdwood8a978232015-05-29 19:06:14 +01002024 /* check and free and dynamic widget kcontrols */
2025 snd_soc_tplg_widget_remove(w);
Lars-Peter Clausenb97e2692015-07-21 18:11:07 +02002026 snd_soc_dapm_free_widget(w);
Liam Girdwood8a978232015-05-29 19:06:14 +01002027 }
Jyri Sarhafd589a12015-11-10 18:12:42 +02002028 snd_soc_dapm_reset_cache(dapm);
Liam Girdwood8a978232015-05-29 19:06:14 +01002029}
2030EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all);
2031
2032/* remove dynamic controls from the component driver */
2033int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index)
2034{
2035 struct snd_soc_dobj *dobj, *next_dobj;
2036 int pass = SOC_TPLG_PASS_END;
2037
2038 /* process the header types from end to start */
2039 while (pass >= SOC_TPLG_PASS_START) {
2040
2041 /* remove mixer controls */
2042 list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list,
2043 list) {
2044
2045 /* match index */
2046 if (dobj->index != index &&
2047 dobj->index != SND_SOC_TPLG_INDEX_ALL)
2048 continue;
2049
2050 switch (dobj->type) {
2051 case SND_SOC_DOBJ_MIXER:
2052 remove_mixer(comp, dobj, pass);
2053 break;
2054 case SND_SOC_DOBJ_ENUM:
2055 remove_enum(comp, dobj, pass);
2056 break;
2057 case SND_SOC_DOBJ_BYTES:
2058 remove_bytes(comp, dobj, pass);
2059 break;
2060 case SND_SOC_DOBJ_WIDGET:
2061 remove_widget(comp, dobj, pass);
2062 break;
2063 case SND_SOC_DOBJ_PCM:
Mengdong Lin64527e82016-01-15 16:13:28 +08002064 remove_dai(comp, dobj, pass);
Liam Girdwood8a978232015-05-29 19:06:14 +01002065 break;
Mengdong Linacfc7d42016-01-15 16:13:37 +08002066 case SND_SOC_DOBJ_DAI_LINK:
2067 remove_link(comp, dobj, pass);
2068 break;
Liam Girdwood8a978232015-05-29 19:06:14 +01002069 default:
2070 dev_err(comp->dev, "ASoC: invalid component type %d for removal\n",
2071 dobj->type);
2072 break;
2073 }
2074 }
2075 pass--;
2076 }
2077
2078 /* let caller know if FW can be freed when no objects are left */
2079 return !list_empty(&comp->dobj_list);
2080}
2081EXPORT_SYMBOL_GPL(snd_soc_tplg_component_remove);