2 * soc-topology.c -- ALSA SoC Topology
4 * Copyright (C) 2012 Texas Instruments Inc.
5 * Copyright (C) 2015 Intel Corporation.
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>
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.
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.
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.
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>
36 #include <sound/tlv.h>
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).
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
48 #define SOC_TPLG_PASS_PCM_DAI 4
49 #define SOC_TPLG_PASS_GRAPH 5
50 #define SOC_TPLG_PASS_PINS 6
51 #define SOC_TPLG_PASS_BE_DAI 7
53 #define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST
54 #define SOC_TPLG_PASS_END SOC_TPLG_PASS_BE_DAI
57 const struct firmware
*fw
;
59 /* runtime FW parsing */
60 const u8
*pos
; /* read postion */
61 const u8
*hdr_pos
; /* header position */
62 unsigned int pass
; /* pass number */
64 /* component caller */
66 struct snd_soc_component
*comp
;
67 u32 index
; /* current block index */
68 u32 req_index
; /* required index, only loaded/free matching blocks */
70 /* vendor specific kcontrol operations */
71 const struct snd_soc_tplg_kcontrol_ops
*io_ops
;
74 /* 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
;
78 /* optional fw loading callbacks to component drivers */
79 struct snd_soc_tplg_ops
*ops
;
82 static int soc_tplg_process_headers(struct soc_tplg
*tplg
);
83 static void soc_tplg_complete(struct soc_tplg
*tplg
);
84 struct snd_soc_dapm_widget
*
85 snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context
*dapm
,
86 const struct snd_soc_dapm_widget
*widget
);
87 struct snd_soc_dapm_widget
*
88 snd_soc_dapm_new_control(struct snd_soc_dapm_context
*dapm
,
89 const struct snd_soc_dapm_widget
*widget
);
91 /* check we dont overflow the data for this control chunk */
92 static 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
)
95 const u8
*end
= tplg
->pos
+ elem_size
* count
;
97 if (end
> tplg
->fw
->data
+ tplg
->fw
->size
) {
98 dev_err(tplg
->dev
, "ASoC: %s overflow end of data\n",
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
) {
107 "ASoC: %s count %d of size %zu is bigger than chunk %zu\n",
108 elem_type
, count
, elem_size
, bytes
);
115 static inline int soc_tplg_is_eof(struct soc_tplg
*tplg
)
117 const u8
*end
= tplg
->hdr_pos
;
119 if (end
>= tplg
->fw
->data
+ tplg
->fw
->size
)
124 static inline unsigned long soc_tplg_get_hdr_offset(struct soc_tplg
*tplg
)
126 return (unsigned long)(tplg
->hdr_pos
- tplg
->fw
->data
);
129 static inline unsigned long soc_tplg_get_offset(struct soc_tplg
*tplg
)
131 return (unsigned long)(tplg
->pos
- tplg
->fw
->data
);
134 /* mapping of Kcontrol types and associated operations. */
135 static 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
,
153 snd_soc_dapm_put_volsw
, snd_soc_info_volsw
},
154 {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
},
164 struct soc_tplg_map
{
169 /* mapping of widget types from UAPI IDs to kernel IDs */
170 static 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
},
189 static int tplc_chan_get_reg(struct soc_tplg
*tplg
,
190 struct snd_soc_tplg_channel
*chan
, int map
)
194 for (i
= 0; i
< SND_SOC_TPLG_MAX_CHAN
; i
++) {
195 if (chan
[i
].id
== map
)
202 static int tplc_chan_get_shift(struct soc_tplg
*tplg
,
203 struct snd_soc_tplg_channel
*chan
, int map
)
207 for (i
= 0; i
< SND_SOC_TPLG_MAX_CHAN
; i
++) {
208 if (chan
[i
].id
== map
)
209 return chan
[i
].shift
;
215 static int get_widget_id(int tplg_type
)
219 for (i
= 0; i
< ARRAY_SIZE(dapm_map
); i
++) {
220 if (tplg_type
== dapm_map
[i
].uid
)
221 return dapm_map
[i
].kid
;
227 static inline void soc_bind_err(struct soc_tplg
*tplg
,
228 struct snd_soc_tplg_ctl_hdr
*hdr
, int index
)
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
));
236 static inline void soc_control_err(struct soc_tplg
*tplg
,
237 struct snd_soc_tplg_ctl_hdr
*hdr
, const char *name
)
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
));
245 /* pass vendor data to component driver for processing */
246 static int soc_tplg_vendor_load_(struct soc_tplg
*tplg
,
247 struct snd_soc_tplg_hdr
*hdr
)
251 if (tplg
->comp
&& tplg
->ops
&& tplg
->ops
->vendor_load
)
252 ret
= tplg
->ops
->vendor_load(tplg
->comp
, hdr
);
254 dev_err(tplg
->dev
, "ASoC: no vendor load callback for ID %d\n",
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
);
268 /* pass vendor data to component driver for processing */
269 static int soc_tplg_vendor_load(struct soc_tplg
*tplg
,
270 struct snd_soc_tplg_hdr
*hdr
)
272 if (tplg
->pass
!= SOC_TPLG_PASS_VENDOR
)
275 return soc_tplg_vendor_load_(tplg
, hdr
);
278 /* optionally pass new dynamic widget to component driver. This is mainly for
279 * external widgets where we can assign private data/ops */
280 static int soc_tplg_widget_load(struct soc_tplg
*tplg
,
281 struct snd_soc_dapm_widget
*w
, struct snd_soc_tplg_dapm_widget
*tplg_w
)
283 if (tplg
->comp
&& tplg
->ops
&& tplg
->ops
->widget_load
)
284 return tplg
->ops
->widget_load(tplg
->comp
, w
, tplg_w
);
289 /* pass DAI configurations to component driver for extra intialization */
290 static int soc_tplg_dai_load(struct soc_tplg
*tplg
,
291 struct snd_soc_dai_driver
*dai_drv
)
293 if (tplg
->comp
&& tplg
->ops
&& tplg
->ops
->dai_load
)
294 return tplg
->ops
->dai_load(tplg
->comp
, dai_drv
);
299 /* pass link configurations to component driver for extra intialization */
300 static int soc_tplg_dai_link_load(struct soc_tplg
*tplg
,
301 struct snd_soc_dai_link
*link
)
303 if (tplg
->comp
&& tplg
->ops
&& tplg
->ops
->link_load
)
304 return tplg
->ops
->link_load(tplg
->comp
, link
);
309 /* tell the component driver that all firmware has been loaded in this request */
310 static void soc_tplg_complete(struct soc_tplg
*tplg
)
312 if (tplg
->comp
&& tplg
->ops
&& tplg
->ops
->complete
)
313 tplg
->ops
->complete(tplg
->comp
);
316 /* add a dynamic kcontrol */
317 static 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
)
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",
330 err
= snd_ctl_add(card
, *kcontrol
);
332 dev_err(dev
, "ASoC: Failed to add %s: %d\n",
333 control_new
->name
, err
);
340 /* add a dynamic kcontrol for component driver */
341 static int soc_tplg_add_kcontrol(struct soc_tplg
*tplg
,
342 struct snd_kcontrol_new
*k
, struct snd_kcontrol
**kcontrol
)
344 struct snd_soc_component
*comp
= tplg
->comp
;
346 return soc_tplg_add_dcontrol(comp
->card
->snd_card
,
347 comp
->dev
, k
, NULL
, comp
, kcontrol
);
350 /* remove a mixer kcontrol */
351 static void remove_mixer(struct snd_soc_component
*comp
,
352 struct snd_soc_dobj
*dobj
, int pass
)
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
;
359 if (pass
!= SOC_TPLG_PASS_MIXER
)
362 if (dobj
->ops
&& dobj
->ops
->control_unload
)
363 dobj
->ops
->control_unload(comp
, dobj
);
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
);
373 /* remove an enum kcontrol */
374 static void remove_enum(struct snd_soc_component
*comp
,
375 struct snd_soc_dobj
*dobj
, int pass
)
377 struct snd_card
*card
= comp
->card
->snd_card
;
378 struct soc_enum
*se
= container_of(dobj
, struct soc_enum
, dobj
);
381 if (pass
!= SOC_TPLG_PASS_MIXER
)
384 if (dobj
->ops
&& dobj
->ops
->control_unload
)
385 dobj
->ops
->control_unload(comp
, dobj
);
387 snd_ctl_remove(card
, se
->dobj
.control
.kcontrol
);
388 list_del(&se
->dobj
.list
);
390 kfree(se
->dobj
.control
.dvalues
);
391 for (i
= 0; i
< se
->items
; i
++)
392 kfree(se
->dobj
.control
.dtexts
[i
]);
396 /* remove a byte kcontrol */
397 static void remove_bytes(struct snd_soc_component
*comp
,
398 struct snd_soc_dobj
*dobj
, int pass
)
400 struct snd_card
*card
= comp
->card
->snd_card
;
401 struct soc_bytes_ext
*sb
=
402 container_of(dobj
, struct soc_bytes_ext
, dobj
);
404 if (pass
!= SOC_TPLG_PASS_MIXER
)
407 if (dobj
->ops
&& dobj
->ops
->control_unload
)
408 dobj
->ops
->control_unload(comp
, dobj
);
410 snd_ctl_remove(card
, sb
->dobj
.control
.kcontrol
);
411 list_del(&sb
->dobj
.list
);
415 /* remove a widget and it's kcontrols - routes must be removed first */
416 static void remove_widget(struct snd_soc_component
*comp
,
417 struct snd_soc_dobj
*dobj
, int pass
)
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
);
424 if (pass
!= SOC_TPLG_PASS_WIDGET
)
427 if (dobj
->ops
&& dobj
->ops
->widget_unload
)
428 dobj
->ops
->widget_unload(comp
, dobj
);
431 * Dynamic Widgets either have 1 enum kcontrol or 1..N mixers.
432 * The enum may either have an array of values or strings.
434 if (dobj
->widget
.kcontrol_enum
) {
435 /* enumerated widget mixer */
436 struct soc_enum
*se
=
437 (struct soc_enum
*)w
->kcontrols
[0]->private_value
;
439 snd_ctl_remove(card
, w
->kcontrols
[0]);
441 kfree(se
->dobj
.control
.dvalues
);
442 for (i
= 0; i
< se
->items
; i
++)
443 kfree(se
->dobj
.control
.dtexts
[i
]);
446 kfree(w
->kcontrol_news
);
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
;
454 kfree(w
->kcontrols
[i
]->tlv
.p
);
456 snd_ctl_remove(card
, w
->kcontrols
[i
]);
459 kfree(w
->kcontrol_news
);
461 /* widget w is freed by soc-dapm.c */
464 /* remove DAI configurations */
465 static void remove_dai(struct snd_soc_component
*comp
,
466 struct snd_soc_dobj
*dobj
, int pass
)
468 struct snd_soc_dai_driver
*dai_drv
=
469 container_of(dobj
, struct snd_soc_dai_driver
, dobj
);
471 if (pass
!= SOC_TPLG_PASS_PCM_DAI
)
474 if (dobj
->ops
&& dobj
->ops
->dai_unload
)
475 dobj
->ops
->dai_unload(comp
, dobj
);
477 list_del(&dobj
->list
);
481 /* remove link configurations */
482 static void remove_link(struct snd_soc_component
*comp
,
483 struct snd_soc_dobj
*dobj
, int pass
)
485 struct snd_soc_dai_link
*link
=
486 container_of(dobj
, struct snd_soc_dai_link
, dobj
);
488 if (pass
!= SOC_TPLG_PASS_PCM_DAI
)
491 if (dobj
->ops
&& dobj
->ops
->link_unload
)
492 dobj
->ops
->link_unload(comp
, dobj
);
494 list_del(&dobj
->list
);
495 snd_soc_remove_dai_link(comp
->card
, link
);
499 /* bind a kcontrol to it's IO handlers */
500 static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr
*hdr
,
501 struct snd_kcontrol_new
*k
,
502 const struct soc_tplg
*tplg
)
504 const struct snd_soc_tplg_kcontrol_ops
*ops
;
505 const struct snd_soc_tplg_bytes_ext_ops
*ext_ops
;
508 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
;
515 sbe
= (struct soc_bytes_ext
*)k
->private_value
;
516 be
= container_of(hdr
, struct snd_soc_tplg_bytes_control
, hdr
);
518 /* TLV bytes controls need standard kcontrol info handler,
519 * TLV callback and extended put/get handlers.
521 k
->info
= snd_soc_bytes_info_ext
;
522 k
->tlv
.c
= snd_soc_bytes_tlv_callback
;
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
;
533 if (sbe
->put
&& sbe
->get
)
539 /* try and map vendor specific kcontrol handlers first */
541 num_ops
= tplg
->io_ops_count
;
542 for (i
= 0; i
< num_ops
; i
++) {
544 if (k
->put
== NULL
&& ops
[i
].id
== hdr
->ops
.put
)
546 if (k
->get
== NULL
&& ops
[i
].id
== hdr
->ops
.get
)
548 if (k
->info
== NULL
&& ops
[i
].id
== hdr
->ops
.info
)
549 k
->info
= ops
[i
].info
;
552 /* vendor specific handlers found ? */
553 if (k
->put
&& k
->get
&& k
->info
)
556 /* none found so try standard kcontrol handlers */
558 num_ops
= ARRAY_SIZE(io_ops
);
559 for (i
= 0; i
< num_ops
; i
++) {
561 if (k
->put
== NULL
&& ops
[i
].id
== hdr
->ops
.put
)
563 if (k
->get
== NULL
&& ops
[i
].id
== hdr
->ops
.get
)
565 if (k
->info
== NULL
&& ops
[i
].id
== hdr
->ops
.info
)
566 k
->info
= ops
[i
].info
;
569 /* standard handlers found ? */
570 if (k
->put
&& k
->get
&& k
->info
)
573 /* nothing to bind */
577 /* bind a widgets to it's evnt handlers */
578 int 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
)
586 for (i
= 0; i
< num_events
; i
++) {
587 if (event_type
== events
[i
].type
) {
589 /* found - so assign event */
590 w
->event
= events
[i
].event_handler
;
598 EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_bind_event
);
600 /* optionally pass new dynamic kcontrol to component driver. */
601 static int soc_tplg_init_kcontrol(struct soc_tplg
*tplg
,
602 struct snd_kcontrol_new
*k
, struct snd_soc_tplg_ctl_hdr
*hdr
)
604 if (tplg
->comp
&& tplg
->ops
&& tplg
->ops
->control_load
)
605 return tplg
->ops
->control_load(tplg
->comp
, k
, hdr
);
611 static int soc_tplg_create_tlv_db_scale(struct soc_tplg
*tplg
,
612 struct snd_kcontrol_new
*kc
, struct snd_soc_tplg_tlv_dbscale
*scale
)
614 unsigned int item_len
= 2 * sizeof(unsigned int);
617 p
= kzalloc(item_len
+ 2 * sizeof(unsigned int), GFP_KERNEL
);
621 p
[0] = SNDRV_CTL_TLVT_DB_SCALE
;
624 p
[3] = (scale
->step
& TLV_DB_SCALE_MASK
)
625 | (scale
->mute
? TLV_DB_SCALE_MUTE
: 0);
627 kc
->tlv
.p
= (void *)p
;
631 static int soc_tplg_create_tlv(struct soc_tplg
*tplg
,
632 struct snd_kcontrol_new
*kc
, struct snd_soc_tplg_ctl_hdr
*tc
)
634 struct snd_soc_tplg_ctl_tlv
*tplg_tlv
;
636 if (!(tc
->access
& SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
))
639 if (!(tc
->access
& SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
)) {
641 switch (tplg_tlv
->type
) {
642 case SNDRV_CTL_TLVT_DB_SCALE
:
643 return soc_tplg_create_tlv_db_scale(tplg
, kc
,
646 /* TODO: add support for other TLV types */
648 dev_dbg(tplg
->dev
, "Unsupported TLV type %d\n",
657 static inline void soc_tplg_free_tlv(struct soc_tplg
*tplg
,
658 struct snd_kcontrol_new
*kc
)
663 static int soc_tplg_dbytes_create(struct soc_tplg
*tplg
, unsigned int count
,
666 struct snd_soc_tplg_bytes_control
*be
;
667 struct soc_bytes_ext
*sbe
;
668 struct snd_kcontrol_new kc
;
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",
679 for (i
= 0; i
< count
; i
++) {
680 be
= (struct snd_soc_tplg_bytes_control
*)tplg
->pos
;
682 /* validate kcontrol */
683 if (strnlen(be
->hdr
.name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
684 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
687 sbe
= kzalloc(sizeof(*sbe
), GFP_KERNEL
);
691 tplg
->pos
+= (sizeof(struct snd_soc_tplg_bytes_control
) +
695 "ASoC: adding bytes kcontrol %s with access 0x%x\n",
696 be
->hdr
.name
, be
->hdr
.access
);
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
;
705 sbe
->dobj
.type
= SND_SOC_DOBJ_BYTES
;
706 sbe
->dobj
.ops
= tplg
->ops
;
707 INIT_LIST_HEAD(&sbe
->dobj
.list
);
709 /* map io handlers */
710 err
= soc_tplg_kcontrol_bind_io(&be
->hdr
, &kc
, tplg
);
712 soc_control_err(tplg
, &be
->hdr
, be
->hdr
.name
);
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
);
721 dev_err(tplg
->dev
, "ASoC: failed to init %s\n",
727 /* register control here */
728 err
= soc_tplg_add_kcontrol(tplg
, &kc
,
729 &sbe
->dobj
.control
.kcontrol
);
731 dev_err(tplg
->dev
, "ASoC: failed to add %s\n",
737 list_add(&sbe
->dobj
.list
, &tplg
->comp
->dobj_list
);
743 static int soc_tplg_dmixer_create(struct soc_tplg
*tplg
, unsigned int count
,
746 struct snd_soc_tplg_mixer_control
*mc
;
747 struct soc_mixer_control
*sm
;
748 struct snd_kcontrol_new kc
;
751 if (soc_tplg_check_elem_count(tplg
,
752 sizeof(struct snd_soc_tplg_mixer_control
),
753 count
, size
, "mixers")) {
755 dev_err(tplg
->dev
, "ASoC: invalid count %d for controls\n",
760 for (i
= 0; i
< count
; i
++) {
761 mc
= (struct snd_soc_tplg_mixer_control
*)tplg
->pos
;
763 /* validate kcontrol */
764 if (strnlen(mc
->hdr
.name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
765 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
768 sm
= kzalloc(sizeof(*sm
), GFP_KERNEL
);
771 tplg
->pos
+= (sizeof(struct snd_soc_tplg_mixer_control
) +
775 "ASoC: adding mixer kcontrol %s with access 0x%x\n",
776 mc
->hdr
.name
, mc
->hdr
.access
);
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
;
784 /* we only support FL/FR channel mapping atm */
785 sm
->reg
= tplc_chan_get_reg(tplg
, mc
->channel
,
787 sm
->rreg
= tplc_chan_get_reg(tplg
, mc
->channel
,
789 sm
->shift
= tplc_chan_get_shift(tplg
, mc
->channel
,
791 sm
->rshift
= tplc_chan_get_shift(tplg
, mc
->channel
,
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
);
803 /* map io handlers */
804 err
= soc_tplg_kcontrol_bind_io(&mc
->hdr
, &kc
, tplg
);
806 soc_control_err(tplg
, &mc
->hdr
, mc
->hdr
.name
);
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
);
815 dev_err(tplg
->dev
, "ASoC: failed to init %s\n",
821 /* create any TLV data */
822 soc_tplg_create_tlv(tplg
, &kc
, &mc
->hdr
);
824 /* register control here */
825 err
= soc_tplg_add_kcontrol(tplg
, &kc
,
826 &sm
->dobj
.control
.kcontrol
);
828 dev_err(tplg
->dev
, "ASoC: failed to add %s\n",
830 soc_tplg_free_tlv(tplg
, &kc
);
835 list_add(&sm
->dobj
.list
, &tplg
->comp
->dobj_list
);
841 static int soc_tplg_denum_create_texts(struct soc_enum
*se
,
842 struct snd_soc_tplg_enum_control
*ec
)
846 se
->dobj
.control
.dtexts
=
847 kzalloc(sizeof(char *) * ec
->items
, GFP_KERNEL
);
848 if (se
->dobj
.control
.dtexts
== NULL
)
851 for (i
= 0; i
< ec
->items
; i
++) {
853 if (strnlen(ec
->texts
[i
], SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
854 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) {
859 se
->dobj
.control
.dtexts
[i
] = kstrdup(ec
->texts
[i
], GFP_KERNEL
);
860 if (!se
->dobj
.control
.dtexts
[i
]) {
869 for (--i
; i
>= 0; i
--)
870 kfree(se
->dobj
.control
.dtexts
[i
]);
871 kfree(se
->dobj
.control
.dtexts
);
875 static int soc_tplg_denum_create_values(struct soc_enum
*se
,
876 struct snd_soc_tplg_enum_control
*ec
)
878 if (ec
->items
> sizeof(*ec
->values
))
881 se
->dobj
.control
.dvalues
= kmemdup(ec
->values
,
882 ec
->items
* sizeof(u32
),
884 if (!se
->dobj
.control
.dvalues
)
890 static int soc_tplg_denum_create(struct soc_tplg
*tplg
, unsigned int count
,
893 struct snd_soc_tplg_enum_control
*ec
;
895 struct snd_kcontrol_new kc
;
898 if (soc_tplg_check_elem_count(tplg
,
899 sizeof(struct snd_soc_tplg_enum_control
),
900 count
, size
, "enums")) {
902 dev_err(tplg
->dev
, "ASoC: invalid count %d for enum controls\n",
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
) +
912 /* validate kcontrol */
913 if (strnlen(ec
->hdr
.name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
914 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
917 se
= kzalloc((sizeof(*se
)), GFP_KERNEL
);
921 dev_dbg(tplg
->dev
, "ASoC: adding enum kcontrol %s size %d\n",
922 ec
->hdr
.name
, ec
->items
);
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
;
930 se
->reg
= tplc_chan_get_reg(tplg
, ec
->channel
, SNDRV_CHMAP_FL
);
931 se
->shift_l
= tplc_chan_get_shift(tplg
, ec
->channel
,
933 se
->shift_r
= tplc_chan_get_shift(tplg
, ec
->channel
,
936 se
->items
= ec
->items
;
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
);
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
);
949 "ASoC: could not create values for %s\n",
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
);
961 "ASoC: could not create texts for %s\n",
969 "ASoC: invalid enum control type %d for %s\n",
970 ec
->hdr
.ops
.info
, ec
->hdr
.name
);
975 /* map io handlers */
976 err
= soc_tplg_kcontrol_bind_io(&ec
->hdr
, &kc
, tplg
);
978 soc_control_err(tplg
, &ec
->hdr
, ec
->hdr
.name
);
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
);
987 dev_err(tplg
->dev
, "ASoC: failed to init %s\n",
993 /* register control here */
994 ret
= soc_tplg_add_kcontrol(tplg
,
995 &kc
, &se
->dobj
.control
.kcontrol
);
997 dev_err(tplg
->dev
, "ASoC: could not add kcontrol %s\n",
1003 list_add(&se
->dobj
.list
, &tplg
->comp
->dobj_list
);
1009 static int soc_tplg_kcontrol_elems_load(struct soc_tplg
*tplg
,
1010 struct snd_soc_tplg_hdr
*hdr
)
1012 struct snd_soc_tplg_ctl_hdr
*control_hdr
;
1015 if (tplg
->pass
!= SOC_TPLG_PASS_MIXER
) {
1016 tplg
->pos
+= hdr
->size
+ hdr
->payload_size
;
1020 dev_dbg(tplg
->dev
, "ASoC: adding %d kcontrols at 0x%lx\n", hdr
->count
,
1021 soc_tplg_get_offset(tplg
));
1023 for (i
= 0; i
< hdr
->count
; i
++) {
1025 control_hdr
= (struct snd_soc_tplg_ctl_hdr
*)tplg
->pos
;
1027 if (control_hdr
->size
!= sizeof(*control_hdr
)) {
1028 dev_err(tplg
->dev
, "ASoC: invalid control size\n");
1032 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
);
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
);
1049 case SND_SOC_TPLG_CTL_BYTES
:
1050 soc_tplg_dbytes_create(tplg
, 1, hdr
->payload_size
);
1053 soc_bind_err(tplg
, control_hdr
, i
);
1061 static int soc_tplg_dapm_graph_elems_load(struct soc_tplg
*tplg
,
1062 struct snd_soc_tplg_hdr
*hdr
)
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
;
1069 if (tplg
->pass
!= SOC_TPLG_PASS_GRAPH
) {
1070 tplg
->pos
+= hdr
->size
+ hdr
->payload_size
;
1074 if (soc_tplg_check_elem_count(tplg
,
1075 sizeof(struct snd_soc_tplg_dapm_graph_elem
),
1076 count
, hdr
->payload_size
, "graph")) {
1078 dev_err(tplg
->dev
, "ASoC: invalid count %d for DAPM routes\n",
1083 dev_dbg(tplg
->dev
, "ASoC: adding %d DAPM routes\n", count
);
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
);
1089 /* validate routes */
1090 if (strnlen(elem
->source
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1091 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1093 if (strnlen(elem
->sink
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1094 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1096 if (strnlen(elem
->control
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1097 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
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
;
1106 route
.control
= elem
->control
;
1108 /* add route, but keep going if some fail */
1109 snd_soc_dapm_add_routes(dapm
, &route
, 1);
1115 static struct snd_kcontrol_new
*soc_tplg_dapm_widget_dmixer_create(
1116 struct soc_tplg
*tplg
, int num_kcontrols
)
1118 struct snd_kcontrol_new
*kc
;
1119 struct soc_mixer_control
*sm
;
1120 struct snd_soc_tplg_mixer_control
*mc
;
1123 kc
= kcalloc(num_kcontrols
, sizeof(*kc
), GFP_KERNEL
);
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
);
1133 tplg
->pos
+= (sizeof(struct snd_soc_tplg_mixer_control
) +
1136 /* validate kcontrol */
1137 if (strnlen(mc
->hdr
.name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1138 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1141 dev_dbg(tplg
->dev
, " adding DAPM widget mixer control %s at %d\n",
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
;
1149 /* we only support FL/FR channel mapping atm */
1150 sm
->reg
= tplc_chan_get_reg(tplg
, mc
->channel
,
1152 sm
->rreg
= tplc_chan_get_reg(tplg
, mc
->channel
,
1154 sm
->shift
= tplc_chan_get_shift(tplg
, mc
->channel
,
1156 sm
->rshift
= tplc_chan_get_shift(tplg
, mc
->channel
,
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
);
1166 /* map io handlers */
1167 err
= soc_tplg_kcontrol_bind_io(&mc
->hdr
, &kc
[i
], tplg
);
1169 soc_control_err(tplg
, &mc
->hdr
, mc
->hdr
.name
);
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
);
1178 dev_err(tplg
->dev
, "ASoC: failed to init %s\n",
1184 /* create any TLV data */
1185 soc_tplg_create_tlv(tplg
, &kc
[i
], &mc
->hdr
);
1192 for (--i
; i
>= 0; i
--)
1193 kfree((void *)kc
[i
].private_value
);
1198 static struct snd_kcontrol_new
*soc_tplg_dapm_widget_denum_create(
1199 struct soc_tplg
*tplg
)
1201 struct snd_kcontrol_new
*kc
;
1202 struct snd_soc_tplg_enum_control
*ec
;
1203 struct soc_enum
*se
;
1206 ec
= (struct snd_soc_tplg_enum_control
*)tplg
->pos
;
1207 tplg
->pos
+= (sizeof(struct snd_soc_tplg_enum_control
) +
1210 /* validate kcontrol */
1211 if (strnlen(ec
->hdr
.name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1212 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1215 kc
= kzalloc(sizeof(*kc
), GFP_KERNEL
);
1219 se
= kzalloc(sizeof(*se
), GFP_KERNEL
);
1223 dev_dbg(tplg
->dev
, " adding DAPM widget enum control %s\n",
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
;
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
);
1236 se
->items
= ec
->items
;
1237 se
->mask
= ec
->mask
;
1238 se
->dobj
.index
= tplg
->index
;
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
);
1245 dev_err(tplg
->dev
, "ASoC: could not create values for %s\n",
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
);
1255 dev_err(tplg
->dev
, "ASoC: could not create texts for %s\n",
1261 dev_err(tplg
->dev
, "ASoC: invalid enum control type %d for %s\n",
1262 ec
->hdr
.ops
.info
, ec
->hdr
.name
);
1266 /* map io handlers */
1267 err
= soc_tplg_kcontrol_bind_io(&ec
->hdr
, kc
, tplg
);
1269 soc_control_err(tplg
, &ec
->hdr
, ec
->hdr
.name
);
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
);
1277 dev_err(tplg
->dev
, "ASoC: failed to init %s\n",
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
]);
1297 static struct snd_kcontrol_new
*soc_tplg_dapm_widget_dbytes_create(
1298 struct soc_tplg
*tplg
, int count
)
1300 struct snd_soc_tplg_bytes_control
*be
;
1301 struct soc_bytes_ext
*sbe
;
1302 struct snd_kcontrol_new
*kc
;
1305 kc
= kcalloc(count
, sizeof(*kc
), GFP_KERNEL
);
1309 for (i
= 0; i
< count
; i
++) {
1310 be
= (struct snd_soc_tplg_bytes_control
*)tplg
->pos
;
1312 /* validate kcontrol */
1313 if (strnlen(be
->hdr
.name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1314 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1317 sbe
= kzalloc(sizeof(*sbe
), GFP_KERNEL
);
1321 tplg
->pos
+= (sizeof(struct snd_soc_tplg_bytes_control
) +
1325 "ASoC: adding bytes kcontrol %s with access 0x%x\n",
1326 be
->hdr
.name
, be
->hdr
.access
);
1328 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
;
1334 INIT_LIST_HEAD(&sbe
->dobj
.list
);
1336 /* map standard io handlers and check for external handlers */
1337 err
= soc_tplg_kcontrol_bind_io(&be
->hdr
, &kc
[i
], tplg
);
1339 soc_control_err(tplg
, &be
->hdr
, be
->hdr
.name
);
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
);
1348 dev_err(tplg
->dev
, "ASoC: failed to init %s\n",
1358 for (--i
; i
>= 0; i
--)
1359 kfree((void *)kc
[i
].private_value
);
1365 static int soc_tplg_dapm_widget_create(struct soc_tplg
*tplg
,
1366 struct snd_soc_tplg_dapm_widget
*w
)
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
;
1374 if (strnlen(w
->name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1375 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1377 if (strnlen(w
->sname
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1378 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1381 dev_dbg(tplg
->dev
, "ASoC: creating DAPM widget %s id %d\n",
1384 memset(&template, 0, sizeof(template));
1386 /* map user to kernel widget ID */
1387 template.id
= get_widget_id(w
->id
);
1388 if (template.id
< 0)
1391 template.name
= kstrdup(w
->name
, GFP_KERNEL
);
1394 template.sname
= kstrdup(w
->sname
, GFP_KERNEL
);
1395 if (!template.sname
) {
1399 template.reg
= w
->reg
;
1400 template.shift
= w
->shift
;
1401 template.mask
= w
->mask
;
1402 template.subseq
= w
->subseq
;
1403 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
;
1410 (sizeof(struct snd_soc_tplg_dapm_widget
) + w
->priv
.size
);
1411 if (w
->num_kcontrols
== 0) {
1412 template.num_kcontrols
= 0;
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
);
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
) {
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
) {
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
) {
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
);
1469 ret
= soc_tplg_widget_load(tplg
, &template, w
);
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);
1478 widget
= snd_soc_dapm_new_control_unlocked(dapm
, &template);
1479 if (IS_ERR(widget
)) {
1480 ret
= PTR_ERR(widget
);
1481 /* Do not nag about probe deferrals */
1482 if (ret
!= -EPROBE_DEFER
)
1484 "ASoC: failed to create widget %s controls (%d)\n",
1488 if (widget
== NULL
) {
1489 dev_err(tplg
->dev
, "ASoC: failed to create widget %s controls\n",
1495 widget
->dobj
.type
= SND_SOC_DOBJ_WIDGET
;
1496 widget
->dobj
.ops
= tplg
->ops
;
1497 widget
->dobj
.index
= tplg
->index
;
1498 kfree(template.sname
);
1499 kfree(template.name
);
1500 list_add(&widget
->dobj
.list
, &tplg
->comp
->dobj_list
);
1504 kfree(template.sname
);
1506 kfree(template.name
);
1510 static int soc_tplg_dapm_widget_elems_load(struct soc_tplg
*tplg
,
1511 struct snd_soc_tplg_hdr
*hdr
)
1513 struct snd_soc_tplg_dapm_widget
*widget
;
1514 int ret
, count
= hdr
->count
, i
;
1516 if (tplg
->pass
!= SOC_TPLG_PASS_WIDGET
)
1519 dev_dbg(tplg
->dev
, "ASoC: adding %d DAPM widgets\n", count
);
1521 for (i
= 0; i
< count
; i
++) {
1522 widget
= (struct snd_soc_tplg_dapm_widget
*) tplg
->pos
;
1523 if (widget
->size
!= sizeof(*widget
)) {
1524 dev_err(tplg
->dev
, "ASoC: invalid widget size\n");
1528 ret
= soc_tplg_dapm_widget_create(tplg
, widget
);
1530 dev_err(tplg
->dev
, "ASoC: failed to load widget %s\n",
1539 static int soc_tplg_dapm_complete(struct soc_tplg
*tplg
)
1541 struct snd_soc_card
*card
= tplg
->comp
->card
;
1544 /* Card might not have been registered at this point.
1545 * If so, just return success.
1547 if (!card
|| !card
->instantiated
) {
1548 dev_warn(tplg
->dev
, "ASoC: Parent card not yet available,"
1549 "Do not add new widgets now\n");
1553 ret
= snd_soc_dapm_new_widgets(card
);
1555 dev_err(tplg
->dev
, "ASoC: failed to create new widgets %d\n",
1561 static void set_stream_info(struct snd_soc_pcm_stream
*stream
,
1562 struct snd_soc_tplg_stream_caps
*caps
)
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
;
1571 stream
->sig_bits
= caps
->sig_bits
;
1574 static void set_dai_flags(struct snd_soc_dai_driver
*dai_drv
,
1575 unsigned int flag_mask
, unsigned int flags
)
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;
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
?
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
?
1592 static int soc_tplg_dai_create(struct soc_tplg
*tplg
,
1593 struct snd_soc_tplg_pcm
*pcm
)
1595 struct snd_soc_dai_driver
*dai_drv
;
1596 struct snd_soc_pcm_stream
*stream
;
1597 struct snd_soc_tplg_stream_caps
*caps
;
1600 dai_drv
= kzalloc(sizeof(struct snd_soc_dai_driver
), GFP_KERNEL
);
1601 if (dai_drv
== NULL
)
1604 dai_drv
->name
= pcm
->dai_name
;
1605 dai_drv
->id
= pcm
->dai_id
;
1607 if (pcm
->playback
) {
1608 stream
= &dai_drv
->playback
;
1609 caps
= &pcm
->caps
[SND_SOC_TPLG_STREAM_PLAYBACK
];
1610 set_stream_info(stream
, caps
);
1614 stream
= &dai_drv
->capture
;
1615 caps
= &pcm
->caps
[SND_SOC_TPLG_STREAM_CAPTURE
];
1616 set_stream_info(stream
, caps
);
1619 /* pass control to component driver for optional further init */
1620 ret
= soc_tplg_dai_load(tplg
, dai_drv
);
1622 dev_err(tplg
->comp
->dev
, "ASoC: DAI loading failed\n");
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
);
1632 /* register the DAI to the component */
1633 return snd_soc_register_dai(tplg
->comp
, dai_drv
);
1636 /* create the FE DAI link */
1637 static int soc_tplg_link_create(struct soc_tplg
*tplg
,
1638 struct snd_soc_tplg_pcm
*pcm
)
1640 struct snd_soc_dai_link
*link
;
1643 link
= kzalloc(sizeof(struct snd_soc_dai_link
), GFP_KERNEL
);
1647 link
->name
= pcm
->pcm_name
;
1648 link
->stream_name
= pcm
->pcm_name
;
1649 link
->id
= pcm
->pcm_id
;
1651 link
->cpu_dai_name
= pcm
->dai_name
;
1652 link
->codec_name
= "snd-soc-dummy";
1653 link
->codec_dai_name
= "snd-soc-dummy-dai";
1657 link
->dpcm_playback
= pcm
->playback
;
1658 link
->dpcm_capture
= pcm
->capture
;
1660 /* pass control to component driver for optional further init */
1661 ret
= soc_tplg_dai_link_load(tplg
, link
);
1663 dev_err(tplg
->comp
->dev
, "ASoC: FE link loading failed\n");
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
);
1673 snd_soc_add_dai_link(tplg
->comp
->card
, link
);
1677 /* create a FE DAI and DAI link from the PCM object */
1678 static int soc_tplg_pcm_create(struct soc_tplg
*tplg
,
1679 struct snd_soc_tplg_pcm
*pcm
)
1683 ret
= soc_tplg_dai_create(tplg
, pcm
);
1687 return soc_tplg_link_create(tplg
, pcm
);
1690 static int soc_tplg_pcm_elems_load(struct soc_tplg
*tplg
,
1691 struct snd_soc_tplg_hdr
*hdr
)
1693 struct snd_soc_tplg_pcm
*pcm
;
1694 int count
= hdr
->count
;
1697 if (tplg
->pass
!= SOC_TPLG_PASS_PCM_DAI
)
1700 if (soc_tplg_check_elem_count(tplg
,
1701 sizeof(struct snd_soc_tplg_pcm
), count
,
1702 hdr
->payload_size
, "PCM DAI")) {
1703 dev_err(tplg
->dev
, "ASoC: invalid count %d for PCM DAI elems\n",
1708 /* create the FE DAIs and DAI links */
1709 pcm
= (struct snd_soc_tplg_pcm
*)tplg
->pos
;
1710 for (i
= 0; i
< count
; i
++) {
1711 if (pcm
->size
!= sizeof(*pcm
)) {
1712 dev_err(tplg
->dev
, "ASoC: invalid pcm size\n");
1716 soc_tplg_pcm_create(tplg
, pcm
);
1720 dev_dbg(tplg
->dev
, "ASoC: adding %d PCM DAIs\n", count
);
1721 tplg
->pos
+= sizeof(struct snd_soc_tplg_pcm
) * count
;
1727 * soc_tplg_be_dai_config - Find and configure an existing BE DAI.
1728 * @tplg: topology context
1729 * @be: topology BE DAI configs.
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.
1734 static int soc_tplg_be_dai_config(struct soc_tplg
*tplg
,
1735 struct snd_soc_tplg_be_dai
*be
)
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
;
1744 dai_component
.dai_name
= be
->dai_name
;
1745 dai
= snd_soc_find_dai(&dai_component
);
1747 dev_err(tplg
->dev
, "ASoC: BE DAI %s not registered\n",
1752 if (be
->dai_id
!= dai
->id
) {
1753 dev_err(tplg
->dev
, "ASoC: BE DAI %s id mismatch\n",
1758 dai_drv
= dai
->driver
;
1763 stream
= &dai_drv
->playback
;
1764 caps
= &be
->caps
[SND_SOC_TPLG_STREAM_PLAYBACK
];
1765 set_stream_info(stream
, caps
);
1769 stream
= &dai_drv
->capture
;
1770 caps
= &be
->caps
[SND_SOC_TPLG_STREAM_CAPTURE
];
1771 set_stream_info(stream
, caps
);
1775 set_dai_flags(dai_drv
, be
->flag_mask
, be
->flags
);
1777 /* pass control to component driver for optional further init */
1778 ret
= soc_tplg_dai_load(tplg
, dai_drv
);
1780 dev_err(tplg
->comp
->dev
, "ASoC: DAI loading failed\n");
1787 static int soc_tplg_be_dai_elems_load(struct soc_tplg
*tplg
,
1788 struct snd_soc_tplg_hdr
*hdr
)
1790 struct snd_soc_tplg_be_dai
*be
;
1791 int count
= hdr
->count
;
1794 if (tplg
->pass
!= SOC_TPLG_PASS_BE_DAI
)
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");
1805 soc_tplg_be_dai_config(tplg
, be
);
1806 tplg
->pos
+= (sizeof(*be
) + be
->priv
.size
);
1809 dev_dbg(tplg
->dev
, "ASoC: Configure %d BE DAIs\n", count
);
1814 static int soc_tplg_manifest_load(struct soc_tplg
*tplg
,
1815 struct snd_soc_tplg_hdr
*hdr
)
1817 struct snd_soc_tplg_manifest
*manifest
;
1819 if (tplg
->pass
!= SOC_TPLG_PASS_MANIFEST
)
1822 manifest
= (struct snd_soc_tplg_manifest
*)tplg
->pos
;
1823 if (manifest
->size
!= sizeof(*manifest
)) {
1824 dev_err(tplg
->dev
, "ASoC: invalid manifest size\n");
1828 tplg
->pos
+= sizeof(struct snd_soc_tplg_manifest
);
1830 if (tplg
->comp
&& tplg
->ops
&& tplg
->ops
->manifest
)
1831 return tplg
->ops
->manifest(tplg
->comp
, manifest
);
1833 dev_err(tplg
->dev
, "ASoC: Firmware manifest not supported\n");
1837 /* validate header magic, size and type */
1838 static int soc_valid_header(struct soc_tplg
*tplg
,
1839 struct snd_soc_tplg_hdr
*hdr
)
1841 if (soc_tplg_get_hdr_offset(tplg
) >= tplg
->fw
->size
)
1844 if (hdr
->size
!= sizeof(*hdr
)) {
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
),
1852 /* big endian firmware objects not supported atm */
1853 if (hdr
->magic
== cpu_to_be32(SND_SOC_TPLG_MAGIC
)) {
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
);
1861 if (hdr
->magic
!= SND_SOC_TPLG_MAGIC
) {
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
);
1869 if (hdr
->abi
!= SND_SOC_TPLG_ABI_VERSION
) {
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
),
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
));
1884 if (tplg
->pass
== hdr
->type
)
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
);
1893 /* check header type and call appropriate handler */
1894 static int soc_tplg_load_header(struct soc_tplg
*tplg
,
1895 struct snd_soc_tplg_hdr
*hdr
)
1897 tplg
->pos
= tplg
->hdr_pos
+ sizeof(struct snd_soc_tplg_hdr
);
1899 /* check for matching ID */
1900 if (hdr
->index
!= tplg
->req_index
&&
1901 hdr
->index
!= SND_SOC_TPLG_INDEX_ALL
)
1904 tplg
->index
= hdr
->index
;
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
:
1916 return soc_tplg_pcm_elems_load(tplg
, hdr
);
1917 case SND_SOC_TPLG_TYPE_BE_DAI
:
1918 return soc_tplg_be_dai_elems_load(tplg
, hdr
);
1919 case SND_SOC_TPLG_TYPE_MANIFEST
:
1920 return soc_tplg_manifest_load(tplg
, hdr
);
1922 /* bespoke vendor data object */
1923 return soc_tplg_vendor_load(tplg
, hdr
);
1929 /* process the topology file headers */
1930 static int soc_tplg_process_headers(struct soc_tplg
*tplg
)
1932 struct snd_soc_tplg_hdr
*hdr
;
1935 tplg
->pass
= SOC_TPLG_PASS_START
;
1937 /* process the header types from start to end */
1938 while (tplg
->pass
<= SOC_TPLG_PASS_END
) {
1940 tplg
->hdr_pos
= tplg
->fw
->data
;
1941 hdr
= (struct snd_soc_tplg_hdr
*)tplg
->hdr_pos
;
1943 while (!soc_tplg_is_eof(tplg
)) {
1945 /* make sure header is valid before loading */
1946 ret
= soc_valid_header(tplg
, hdr
);
1952 /* load the header object */
1953 ret
= soc_tplg_load_header(tplg
, hdr
);
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
;
1963 /* next data type pass */
1967 /* signal DAPM we are complete */
1968 ret
= soc_tplg_dapm_complete(tplg
);
1971 "ASoC: failed to initialise DAPM from Firmware\n");
1976 static int soc_tplg_load(struct soc_tplg
*tplg
)
1980 ret
= soc_tplg_process_headers(tplg
);
1982 soc_tplg_complete(tplg
);
1987 /* load audio component topology from "firmware" file */
1988 int snd_soc_tplg_component_load(struct snd_soc_component
*comp
,
1989 struct snd_soc_tplg_ops
*ops
, const struct firmware
*fw
, u32 id
)
1991 struct soc_tplg tplg
;
1993 /* setup parsing context */
1994 memset(&tplg
, 0, sizeof(tplg
));
1996 tplg
.dev
= comp
->dev
;
1999 tplg
.req_index
= id
;
2000 tplg
.io_ops
= ops
->io_ops
;
2001 tplg
.io_ops_count
= ops
->io_ops_count
;
2002 tplg
.bytes_ext_ops
= ops
->bytes_ext_ops
;
2003 tplg
.bytes_ext_ops_count
= ops
->bytes_ext_ops_count
;
2005 return soc_tplg_load(&tplg
);
2007 EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load
);
2009 /* remove this dynamic widget */
2010 void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget
*w
)
2012 /* make sure we are a widget */
2013 if (w
->dobj
.type
!= SND_SOC_DOBJ_WIDGET
)
2016 remove_widget(w
->dapm
->component
, &w
->dobj
, SOC_TPLG_PASS_WIDGET
);
2018 EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove
);
2020 /* remove all dynamic widgets from this DAPM context */
2021 void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context
*dapm
,
2024 struct snd_soc_dapm_widget
*w
, *next_w
;
2026 list_for_each_entry_safe(w
, next_w
, &dapm
->card
->widgets
, list
) {
2028 /* make sure we are a widget with correct context */
2029 if (w
->dobj
.type
!= SND_SOC_DOBJ_WIDGET
|| w
->dapm
!= dapm
)
2033 if (w
->dobj
.index
!= index
&&
2034 w
->dobj
.index
!= SND_SOC_TPLG_INDEX_ALL
)
2036 /* check and free and dynamic widget kcontrols */
2037 snd_soc_tplg_widget_remove(w
);
2038 snd_soc_dapm_free_widget(w
);
2040 snd_soc_dapm_reset_cache(dapm
);
2042 EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all
);
2044 /* remove dynamic controls from the component driver */
2045 int snd_soc_tplg_component_remove(struct snd_soc_component
*comp
, u32 index
)
2047 struct snd_soc_dobj
*dobj
, *next_dobj
;
2048 int pass
= SOC_TPLG_PASS_END
;
2050 /* process the header types from end to start */
2051 while (pass
>= SOC_TPLG_PASS_START
) {
2053 /* remove mixer controls */
2054 list_for_each_entry_safe(dobj
, next_dobj
, &comp
->dobj_list
,
2058 if (dobj
->index
!= index
&&
2059 dobj
->index
!= SND_SOC_TPLG_INDEX_ALL
)
2062 switch (dobj
->type
) {
2063 case SND_SOC_DOBJ_MIXER
:
2064 remove_mixer(comp
, dobj
, pass
);
2066 case SND_SOC_DOBJ_ENUM
:
2067 remove_enum(comp
, dobj
, pass
);
2069 case SND_SOC_DOBJ_BYTES
:
2070 remove_bytes(comp
, dobj
, pass
);
2072 case SND_SOC_DOBJ_WIDGET
:
2073 remove_widget(comp
, dobj
, pass
);
2075 case SND_SOC_DOBJ_PCM
:
2076 remove_dai(comp
, dobj
, pass
);
2078 case SND_SOC_DOBJ_DAI_LINK
:
2079 remove_link(comp
, dobj
, pass
);
2082 dev_err(comp
->dev
, "ASoC: invalid component type %d for removal\n",
2090 /* let caller know if FW can be freed when no objects are left */
2091 return !list_empty(&comp
->dobj_list
);
2093 EXPORT_SYMBOL_GPL(snd_soc_tplg_component_remove
);