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",
1189 for (--i
; i
>= 0; i
--)
1190 kfree((void *)kc
[i
].private_value
);
1195 static struct snd_kcontrol_new
*soc_tplg_dapm_widget_denum_create(
1196 struct soc_tplg
*tplg
)
1198 struct snd_kcontrol_new
*kc
;
1199 struct snd_soc_tplg_enum_control
*ec
;
1200 struct soc_enum
*se
;
1203 ec
= (struct snd_soc_tplg_enum_control
*)tplg
->pos
;
1204 tplg
->pos
+= (sizeof(struct snd_soc_tplg_enum_control
) +
1207 /* validate kcontrol */
1208 if (strnlen(ec
->hdr
.name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1209 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1212 kc
= kzalloc(sizeof(*kc
), GFP_KERNEL
);
1216 se
= kzalloc(sizeof(*se
), GFP_KERNEL
);
1220 dev_dbg(tplg
->dev
, " adding DAPM widget enum control %s\n",
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
;
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
);
1233 se
->items
= ec
->items
;
1234 se
->mask
= ec
->mask
;
1235 se
->dobj
.index
= tplg
->index
;
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
);
1242 dev_err(tplg
->dev
, "ASoC: could not create values for %s\n",
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
);
1252 dev_err(tplg
->dev
, "ASoC: could not create texts for %s\n",
1258 dev_err(tplg
->dev
, "ASoC: invalid enum control type %d for %s\n",
1259 ec
->hdr
.ops
.info
, ec
->hdr
.name
);
1263 /* map io handlers */
1264 err
= soc_tplg_kcontrol_bind_io(&ec
->hdr
, kc
, tplg
);
1266 soc_control_err(tplg
, &ec
->hdr
, ec
->hdr
.name
);
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
);
1274 dev_err(tplg
->dev
, "ASoC: failed to init %s\n",
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
]);
1294 static struct snd_kcontrol_new
*soc_tplg_dapm_widget_dbytes_create(
1295 struct soc_tplg
*tplg
, int count
)
1297 struct snd_soc_tplg_bytes_control
*be
;
1298 struct soc_bytes_ext
*sbe
;
1299 struct snd_kcontrol_new
*kc
;
1302 kc
= kcalloc(count
, sizeof(*kc
), GFP_KERNEL
);
1306 for (i
= 0; i
< count
; i
++) {
1307 be
= (struct snd_soc_tplg_bytes_control
*)tplg
->pos
;
1309 /* validate kcontrol */
1310 if (strnlen(be
->hdr
.name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1311 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1314 sbe
= kzalloc(sizeof(*sbe
), GFP_KERNEL
);
1318 tplg
->pos
+= (sizeof(struct snd_soc_tplg_bytes_control
) +
1322 "ASoC: adding bytes kcontrol %s with access 0x%x\n",
1323 be
->hdr
.name
, be
->hdr
.access
);
1325 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
;
1331 INIT_LIST_HEAD(&sbe
->dobj
.list
);
1333 /* map standard io handlers and check for external handlers */
1334 err
= soc_tplg_kcontrol_bind_io(&be
->hdr
, &kc
[i
], tplg
);
1336 soc_control_err(tplg
, &be
->hdr
, be
->hdr
.name
);
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
);
1345 dev_err(tplg
->dev
, "ASoC: failed to init %s\n",
1355 for (--i
; i
>= 0; i
--)
1356 kfree((void *)kc
[i
].private_value
);
1362 static int soc_tplg_dapm_widget_create(struct soc_tplg
*tplg
,
1363 struct snd_soc_tplg_dapm_widget
*w
)
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
;
1371 if (strnlen(w
->name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1372 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1374 if (strnlen(w
->sname
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) ==
1375 SNDRV_CTL_ELEM_ID_NAME_MAXLEN
)
1378 dev_dbg(tplg
->dev
, "ASoC: creating DAPM widget %s id %d\n",
1381 memset(&template, 0, sizeof(template));
1383 /* map user to kernel widget ID */
1384 template.id
= get_widget_id(w
->id
);
1385 if (template.id
< 0)
1388 template.name
= kstrdup(w
->name
, GFP_KERNEL
);
1391 template.sname
= kstrdup(w
->sname
, GFP_KERNEL
);
1392 if (!template.sname
) {
1396 template.reg
= w
->reg
;
1397 template.shift
= w
->shift
;
1398 template.mask
= w
->mask
;
1399 template.subseq
= w
->subseq
;
1400 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
;
1407 (sizeof(struct snd_soc_tplg_dapm_widget
) + w
->priv
.size
);
1408 if (w
->num_kcontrols
== 0) {
1409 template.num_kcontrols
= 0;
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
);
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
) {
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
) {
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
) {
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
);
1466 ret
= soc_tplg_widget_load(tplg
, &template, w
);
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);
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",
1483 widget
->dobj
.type
= SND_SOC_DOBJ_WIDGET
;
1484 widget
->dobj
.ops
= tplg
->ops
;
1485 widget
->dobj
.index
= tplg
->index
;
1486 kfree(template.sname
);
1487 kfree(template.name
);
1488 list_add(&widget
->dobj
.list
, &tplg
->comp
->dobj_list
);
1492 kfree(template.sname
);
1494 kfree(template.name
);
1498 static int soc_tplg_dapm_widget_elems_load(struct soc_tplg
*tplg
,
1499 struct snd_soc_tplg_hdr
*hdr
)
1501 struct snd_soc_tplg_dapm_widget
*widget
;
1502 int ret
, count
= hdr
->count
, i
;
1504 if (tplg
->pass
!= SOC_TPLG_PASS_WIDGET
)
1507 dev_dbg(tplg
->dev
, "ASoC: adding %d DAPM widgets\n", count
);
1509 for (i
= 0; i
< count
; i
++) {
1510 widget
= (struct snd_soc_tplg_dapm_widget
*) tplg
->pos
;
1511 if (widget
->size
!= sizeof(*widget
)) {
1512 dev_err(tplg
->dev
, "ASoC: invalid widget size\n");
1516 ret
= soc_tplg_dapm_widget_create(tplg
, widget
);
1518 dev_err(tplg
->dev
, "ASoC: failed to load widget %s\n",
1527 static int soc_tplg_dapm_complete(struct soc_tplg
*tplg
)
1529 struct snd_soc_card
*card
= tplg
->comp
->card
;
1532 /* Card might not have been registered at this point.
1533 * If so, just return success.
1535 if (!card
|| !card
->instantiated
) {
1536 dev_warn(tplg
->dev
, "ASoC: Parent card not yet available,"
1537 "Do not add new widgets now\n");
1541 ret
= snd_soc_dapm_new_widgets(card
);
1543 dev_err(tplg
->dev
, "ASoC: failed to create new widgets %d\n",
1549 static void set_stream_info(struct snd_soc_pcm_stream
*stream
,
1550 struct snd_soc_tplg_stream_caps
*caps
)
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
;
1559 stream
->sig_bits
= caps
->sig_bits
;
1562 static void set_dai_flags(struct snd_soc_dai_driver
*dai_drv
,
1563 unsigned int flag_mask
, unsigned int flags
)
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;
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
?
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
?
1580 static int soc_tplg_dai_create(struct soc_tplg
*tplg
,
1581 struct snd_soc_tplg_pcm
*pcm
)
1583 struct snd_soc_dai_driver
*dai_drv
;
1584 struct snd_soc_pcm_stream
*stream
;
1585 struct snd_soc_tplg_stream_caps
*caps
;
1588 dai_drv
= kzalloc(sizeof(struct snd_soc_dai_driver
), GFP_KERNEL
);
1589 if (dai_drv
== NULL
)
1592 dai_drv
->name
= pcm
->dai_name
;
1593 dai_drv
->id
= pcm
->dai_id
;
1595 if (pcm
->playback
) {
1596 stream
= &dai_drv
->playback
;
1597 caps
= &pcm
->caps
[SND_SOC_TPLG_STREAM_PLAYBACK
];
1598 set_stream_info(stream
, caps
);
1602 stream
= &dai_drv
->capture
;
1603 caps
= &pcm
->caps
[SND_SOC_TPLG_STREAM_CAPTURE
];
1604 set_stream_info(stream
, caps
);
1607 /* pass control to component driver for optional further init */
1608 ret
= soc_tplg_dai_load(tplg
, dai_drv
);
1610 dev_err(tplg
->comp
->dev
, "ASoC: DAI loading failed\n");
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
);
1620 /* register the DAI to the component */
1621 return snd_soc_register_dai(tplg
->comp
, dai_drv
);
1624 /* create the FE DAI link */
1625 static int soc_tplg_link_create(struct soc_tplg
*tplg
,
1626 struct snd_soc_tplg_pcm
*pcm
)
1628 struct snd_soc_dai_link
*link
;
1631 link
= kzalloc(sizeof(struct snd_soc_dai_link
), GFP_KERNEL
);
1635 link
->name
= pcm
->pcm_name
;
1636 link
->stream_name
= pcm
->pcm_name
;
1637 link
->id
= pcm
->pcm_id
;
1639 link
->cpu_dai_name
= pcm
->dai_name
;
1640 link
->codec_name
= "snd-soc-dummy";
1641 link
->codec_dai_name
= "snd-soc-dummy-dai";
1645 link
->dpcm_playback
= pcm
->playback
;
1646 link
->dpcm_capture
= pcm
->capture
;
1648 /* pass control to component driver for optional further init */
1649 ret
= soc_tplg_dai_link_load(tplg
, link
);
1651 dev_err(tplg
->comp
->dev
, "ASoC: FE link loading failed\n");
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
);
1661 snd_soc_add_dai_link(tplg
->comp
->card
, link
);
1665 /* create a FE DAI and DAI link from the PCM object */
1666 static int soc_tplg_pcm_create(struct soc_tplg
*tplg
,
1667 struct snd_soc_tplg_pcm
*pcm
)
1671 ret
= soc_tplg_dai_create(tplg
, pcm
);
1675 return soc_tplg_link_create(tplg
, pcm
);
1678 static int soc_tplg_pcm_elems_load(struct soc_tplg
*tplg
,
1679 struct snd_soc_tplg_hdr
*hdr
)
1681 struct snd_soc_tplg_pcm
*pcm
;
1682 int count
= hdr
->count
;
1685 if (tplg
->pass
!= SOC_TPLG_PASS_PCM_DAI
)
1688 if (soc_tplg_check_elem_count(tplg
,
1689 sizeof(struct snd_soc_tplg_pcm
), count
,
1690 hdr
->payload_size
, "PCM DAI")) {
1691 dev_err(tplg
->dev
, "ASoC: invalid count %d for PCM DAI elems\n",
1696 /* create the FE DAIs and DAI links */
1697 pcm
= (struct snd_soc_tplg_pcm
*)tplg
->pos
;
1698 for (i
= 0; i
< count
; i
++) {
1699 if (pcm
->size
!= sizeof(*pcm
)) {
1700 dev_err(tplg
->dev
, "ASoC: invalid pcm size\n");
1704 soc_tplg_pcm_create(tplg
, pcm
);
1708 dev_dbg(tplg
->dev
, "ASoC: adding %d PCM DAIs\n", count
);
1709 tplg
->pos
+= sizeof(struct snd_soc_tplg_pcm
) * count
;
1715 * soc_tplg_be_dai_config - Find and configure an existing BE DAI.
1716 * @tplg: topology context
1717 * @be: topology BE DAI configs.
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.
1722 static int soc_tplg_be_dai_config(struct soc_tplg
*tplg
,
1723 struct snd_soc_tplg_be_dai
*be
)
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
;
1732 dai_component
.dai_name
= be
->dai_name
;
1733 dai
= snd_soc_find_dai(&dai_component
);
1735 dev_err(tplg
->dev
, "ASoC: BE DAI %s not registered\n",
1740 if (be
->dai_id
!= dai
->id
) {
1741 dev_err(tplg
->dev
, "ASoC: BE DAI %s id mismatch\n",
1746 dai_drv
= dai
->driver
;
1751 stream
= &dai_drv
->playback
;
1752 caps
= &be
->caps
[SND_SOC_TPLG_STREAM_PLAYBACK
];
1753 set_stream_info(stream
, caps
);
1757 stream
= &dai_drv
->capture
;
1758 caps
= &be
->caps
[SND_SOC_TPLG_STREAM_CAPTURE
];
1759 set_stream_info(stream
, caps
);
1763 set_dai_flags(dai_drv
, be
->flag_mask
, be
->flags
);
1765 /* pass control to component driver for optional further init */
1766 ret
= soc_tplg_dai_load(tplg
, dai_drv
);
1768 dev_err(tplg
->comp
->dev
, "ASoC: DAI loading failed\n");
1775 static int soc_tplg_be_dai_elems_load(struct soc_tplg
*tplg
,
1776 struct snd_soc_tplg_hdr
*hdr
)
1778 struct snd_soc_tplg_be_dai
*be
;
1779 int count
= hdr
->count
;
1782 if (tplg
->pass
!= SOC_TPLG_PASS_BE_DAI
)
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");
1793 soc_tplg_be_dai_config(tplg
, be
);
1794 tplg
->pos
+= (sizeof(*be
) + be
->priv
.size
);
1797 dev_dbg(tplg
->dev
, "ASoC: Configure %d BE DAIs\n", count
);
1802 static int soc_tplg_manifest_load(struct soc_tplg
*tplg
,
1803 struct snd_soc_tplg_hdr
*hdr
)
1805 struct snd_soc_tplg_manifest
*manifest
;
1807 if (tplg
->pass
!= SOC_TPLG_PASS_MANIFEST
)
1810 manifest
= (struct snd_soc_tplg_manifest
*)tplg
->pos
;
1811 if (manifest
->size
!= sizeof(*manifest
)) {
1812 dev_err(tplg
->dev
, "ASoC: invalid manifest size\n");
1816 tplg
->pos
+= sizeof(struct snd_soc_tplg_manifest
);
1818 if (tplg
->comp
&& tplg
->ops
&& tplg
->ops
->manifest
)
1819 return tplg
->ops
->manifest(tplg
->comp
, manifest
);
1821 dev_err(tplg
->dev
, "ASoC: Firmware manifest not supported\n");
1825 /* validate header magic, size and type */
1826 static int soc_valid_header(struct soc_tplg
*tplg
,
1827 struct snd_soc_tplg_hdr
*hdr
)
1829 if (soc_tplg_get_hdr_offset(tplg
) >= tplg
->fw
->size
)
1832 if (hdr
->size
!= sizeof(*hdr
)) {
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
),
1840 /* big endian firmware objects not supported atm */
1841 if (hdr
->magic
== cpu_to_be32(SND_SOC_TPLG_MAGIC
)) {
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
);
1849 if (hdr
->magic
!= SND_SOC_TPLG_MAGIC
) {
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
);
1857 if (hdr
->abi
!= SND_SOC_TPLG_ABI_VERSION
) {
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
),
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
));
1872 if (tplg
->pass
== hdr
->type
)
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
);
1881 /* check header type and call appropriate handler */
1882 static int soc_tplg_load_header(struct soc_tplg
*tplg
,
1883 struct snd_soc_tplg_hdr
*hdr
)
1885 tplg
->pos
= tplg
->hdr_pos
+ sizeof(struct snd_soc_tplg_hdr
);
1887 /* check for matching ID */
1888 if (hdr
->index
!= tplg
->req_index
&&
1889 hdr
->index
!= SND_SOC_TPLG_INDEX_ALL
)
1892 tplg
->index
= hdr
->index
;
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
:
1904 return soc_tplg_pcm_elems_load(tplg
, hdr
);
1905 case SND_SOC_TPLG_TYPE_BE_DAI
:
1906 return soc_tplg_be_dai_elems_load(tplg
, hdr
);
1907 case SND_SOC_TPLG_TYPE_MANIFEST
:
1908 return soc_tplg_manifest_load(tplg
, hdr
);
1910 /* bespoke vendor data object */
1911 return soc_tplg_vendor_load(tplg
, hdr
);
1917 /* process the topology file headers */
1918 static int soc_tplg_process_headers(struct soc_tplg
*tplg
)
1920 struct snd_soc_tplg_hdr
*hdr
;
1923 tplg
->pass
= SOC_TPLG_PASS_START
;
1925 /* process the header types from start to end */
1926 while (tplg
->pass
<= SOC_TPLG_PASS_END
) {
1928 tplg
->hdr_pos
= tplg
->fw
->data
;
1929 hdr
= (struct snd_soc_tplg_hdr
*)tplg
->hdr_pos
;
1931 while (!soc_tplg_is_eof(tplg
)) {
1933 /* make sure header is valid before loading */
1934 ret
= soc_valid_header(tplg
, hdr
);
1940 /* load the header object */
1941 ret
= soc_tplg_load_header(tplg
, hdr
);
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
;
1951 /* next data type pass */
1955 /* signal DAPM we are complete */
1956 ret
= soc_tplg_dapm_complete(tplg
);
1959 "ASoC: failed to initialise DAPM from Firmware\n");
1964 static int soc_tplg_load(struct soc_tplg
*tplg
)
1968 ret
= soc_tplg_process_headers(tplg
);
1970 soc_tplg_complete(tplg
);
1975 /* load audio component topology from "firmware" file */
1976 int snd_soc_tplg_component_load(struct snd_soc_component
*comp
,
1977 struct snd_soc_tplg_ops
*ops
, const struct firmware
*fw
, u32 id
)
1979 struct soc_tplg tplg
;
1981 /* setup parsing context */
1982 memset(&tplg
, 0, sizeof(tplg
));
1984 tplg
.dev
= comp
->dev
;
1987 tplg
.req_index
= id
;
1988 tplg
.io_ops
= ops
->io_ops
;
1989 tplg
.io_ops_count
= ops
->io_ops_count
;
1990 tplg
.bytes_ext_ops
= ops
->bytes_ext_ops
;
1991 tplg
.bytes_ext_ops_count
= ops
->bytes_ext_ops_count
;
1993 return soc_tplg_load(&tplg
);
1995 EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load
);
1997 /* remove this dynamic widget */
1998 void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget
*w
)
2000 /* make sure we are a widget */
2001 if (w
->dobj
.type
!= SND_SOC_DOBJ_WIDGET
)
2004 remove_widget(w
->dapm
->component
, &w
->dobj
, SOC_TPLG_PASS_WIDGET
);
2006 EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove
);
2008 /* remove all dynamic widgets from this DAPM context */
2009 void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context
*dapm
,
2012 struct snd_soc_dapm_widget
*w
, *next_w
;
2014 list_for_each_entry_safe(w
, next_w
, &dapm
->card
->widgets
, list
) {
2016 /* make sure we are a widget with correct context */
2017 if (w
->dobj
.type
!= SND_SOC_DOBJ_WIDGET
|| w
->dapm
!= dapm
)
2021 if (w
->dobj
.index
!= index
&&
2022 w
->dobj
.index
!= SND_SOC_TPLG_INDEX_ALL
)
2024 /* check and free and dynamic widget kcontrols */
2025 snd_soc_tplg_widget_remove(w
);
2026 snd_soc_dapm_free_widget(w
);
2028 snd_soc_dapm_reset_cache(dapm
);
2030 EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all
);
2032 /* remove dynamic controls from the component driver */
2033 int snd_soc_tplg_component_remove(struct snd_soc_component
*comp
, u32 index
)
2035 struct snd_soc_dobj
*dobj
, *next_dobj
;
2036 int pass
= SOC_TPLG_PASS_END
;
2038 /* process the header types from end to start */
2039 while (pass
>= SOC_TPLG_PASS_START
) {
2041 /* remove mixer controls */
2042 list_for_each_entry_safe(dobj
, next_dobj
, &comp
->dobj_list
,
2046 if (dobj
->index
!= index
&&
2047 dobj
->index
!= SND_SOC_TPLG_INDEX_ALL
)
2050 switch (dobj
->type
) {
2051 case SND_SOC_DOBJ_MIXER
:
2052 remove_mixer(comp
, dobj
, pass
);
2054 case SND_SOC_DOBJ_ENUM
:
2055 remove_enum(comp
, dobj
, pass
);
2057 case SND_SOC_DOBJ_BYTES
:
2058 remove_bytes(comp
, dobj
, pass
);
2060 case SND_SOC_DOBJ_WIDGET
:
2061 remove_widget(comp
, dobj
, pass
);
2063 case SND_SOC_DOBJ_PCM
:
2064 remove_dai(comp
, dobj
, pass
);
2066 case SND_SOC_DOBJ_DAI_LINK
:
2067 remove_link(comp
, dobj
, pass
);
2070 dev_err(comp
->dev
, "ASoC: invalid component type %d for removal\n",
2078 /* let caller know if FW can be freed when no objects are left */
2079 return !list_empty(&comp
->dobj_list
);
2081 EXPORT_SYMBOL_GPL(snd_soc_tplg_component_remove
);