1 /* 2 * soc-topology.c -- ALSA SoC Topology 3 * 4 * Copyright (C) 2012 Texas Instruments Inc. 5 * Copyright (C) 2015 Intel Corporation. 6 * 7 * Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com> 8 * K, Mythri P <mythri.p.k@intel.com> 9 * Prusty, Subhransu S <subhransu.s.prusty@intel.com> 10 * B, Jayachandran <jayachandran.b@intel.com> 11 * Abdullah, Omair M <omair.m.abdullah@intel.com> 12 * Jin, Yao <yao.jin@intel.com> 13 * Lin, Mengdong <mengdong.lin@intel.com> 14 * 15 * This program is free software; you can redistribute it and/or modify it 16 * under the terms of the GNU General Public License as published by the 17 * Free Software Foundation; either version 2 of the License, or (at your 18 * option) any later version. 19 * 20 * Add support to read audio firmware topology alongside firmware text. The 21 * topology data can contain kcontrols, DAPM graphs, widgets, DAIs, DAI links, 22 * equalizers, firmware, coefficients etc. 23 * 24 * This file only manages the core ALSA and ASoC components, all other bespoke 25 * firmware topology data is passed to component drivers for bespoke handling. 26 */ 27 28 #include <linux/kernel.h> 29 #include <linux/export.h> 30 #include <linux/list.h> 31 #include <linux/firmware.h> 32 #include <linux/slab.h> 33 #include <sound/soc.h> 34 #include <sound/soc-dapm.h> 35 #include <sound/soc-topology.h> 36 #include <sound/tlv.h> 37 38 /* 39 * We make several passes over the data (since it wont necessarily be ordered) 40 * and process objects in the following order. This guarantees the component 41 * drivers will be ready with any vendor data before the mixers and DAPM objects 42 * are loaded (that may make use of the vendor data). 43 */ 44 #define SOC_TPLG_PASS_MANIFEST 0 45 #define SOC_TPLG_PASS_VENDOR 1 46 #define SOC_TPLG_PASS_MIXER 2 47 #define SOC_TPLG_PASS_WIDGET 3 48 #define SOC_TPLG_PASS_PCM_DAI 4 49 #define SOC_TPLG_PASS_GRAPH 5 50 #define SOC_TPLG_PASS_PINS 6 51 52 #define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST 53 #define SOC_TPLG_PASS_END SOC_TPLG_PASS_PINS 54 55 struct soc_tplg { 56 const struct firmware *fw; 57 58 /* runtime FW parsing */ 59 const u8 *pos; /* read postion */ 60 const u8 *hdr_pos; /* header position */ 61 unsigned int pass; /* pass number */ 62 63 /* component caller */ 64 struct device *dev; 65 struct snd_soc_component *comp; 66 u32 index; /* current block index */ 67 u32 req_index; /* required index, only loaded/free matching blocks */ 68 69 /* vendor specific kcontrol operations */ 70 const struct snd_soc_tplg_kcontrol_ops *io_ops; 71 int io_ops_count; 72 73 /* vendor specific bytes ext handlers, for TLV bytes controls */ 74 const struct snd_soc_tplg_bytes_ext_ops *bytes_ext_ops; 75 int bytes_ext_ops_count; 76 77 /* optional fw loading callbacks to component drivers */ 78 struct snd_soc_tplg_ops *ops; 79 }; 80 81 static int soc_tplg_process_headers(struct soc_tplg *tplg); 82 static void soc_tplg_complete(struct soc_tplg *tplg); 83 struct snd_soc_dapm_widget * 84 snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, 85 const struct snd_soc_dapm_widget *widget); 86 struct snd_soc_dapm_widget * 87 snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, 88 const struct snd_soc_dapm_widget *widget); 89 90 /* check we dont overflow the data for this control chunk */ 91 static int soc_tplg_check_elem_count(struct soc_tplg *tplg, size_t elem_size, 92 unsigned int count, size_t bytes, const char *elem_type) 93 { 94 const u8 *end = tplg->pos + elem_size * count; 95 96 if (end > tplg->fw->data + tplg->fw->size) { 97 dev_err(tplg->dev, "ASoC: %s overflow end of data\n", 98 elem_type); 99 return -EINVAL; 100 } 101 102 /* check there is enough room in chunk for control. 103 extra bytes at the end of control are for vendor data here */ 104 if (elem_size * count > bytes) { 105 dev_err(tplg->dev, 106 "ASoC: %s count %d of size %zu is bigger than chunk %zu\n", 107 elem_type, count, elem_size, bytes); 108 return -EINVAL; 109 } 110 111 return 0; 112 } 113 114 static inline int soc_tplg_is_eof(struct soc_tplg *tplg) 115 { 116 const u8 *end = tplg->hdr_pos; 117 118 if (end >= tplg->fw->data + tplg->fw->size) 119 return 1; 120 return 0; 121 } 122 123 static inline unsigned long soc_tplg_get_hdr_offset(struct soc_tplg *tplg) 124 { 125 return (unsigned long)(tplg->hdr_pos - tplg->fw->data); 126 } 127 128 static inline unsigned long soc_tplg_get_offset(struct soc_tplg *tplg) 129 { 130 return (unsigned long)(tplg->pos - tplg->fw->data); 131 } 132 133 /* mapping of Kcontrol types and associated operations. */ 134 static const struct snd_soc_tplg_kcontrol_ops io_ops[] = { 135 {SND_SOC_TPLG_CTL_VOLSW, snd_soc_get_volsw, 136 snd_soc_put_volsw, snd_soc_info_volsw}, 137 {SND_SOC_TPLG_CTL_VOLSW_SX, snd_soc_get_volsw_sx, 138 snd_soc_put_volsw_sx, NULL}, 139 {SND_SOC_TPLG_CTL_ENUM, snd_soc_get_enum_double, 140 snd_soc_put_enum_double, snd_soc_info_enum_double}, 141 {SND_SOC_TPLG_CTL_ENUM_VALUE, snd_soc_get_enum_double, 142 snd_soc_put_enum_double, NULL}, 143 {SND_SOC_TPLG_CTL_BYTES, snd_soc_bytes_get, 144 snd_soc_bytes_put, snd_soc_bytes_info}, 145 {SND_SOC_TPLG_CTL_RANGE, snd_soc_get_volsw_range, 146 snd_soc_put_volsw_range, snd_soc_info_volsw_range}, 147 {SND_SOC_TPLG_CTL_VOLSW_XR_SX, snd_soc_get_xr_sx, 148 snd_soc_put_xr_sx, snd_soc_info_xr_sx}, 149 {SND_SOC_TPLG_CTL_STROBE, snd_soc_get_strobe, 150 snd_soc_put_strobe, NULL}, 151 {SND_SOC_TPLG_DAPM_CTL_VOLSW, snd_soc_dapm_get_volsw, 152 snd_soc_dapm_put_volsw, snd_soc_info_volsw}, 153 {SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE, snd_soc_dapm_get_enum_double, 154 snd_soc_dapm_put_enum_double, snd_soc_info_enum_double}, 155 {SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT, snd_soc_dapm_get_enum_double, 156 snd_soc_dapm_put_enum_double, NULL}, 157 {SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE, snd_soc_dapm_get_enum_double, 158 snd_soc_dapm_put_enum_double, NULL}, 159 {SND_SOC_TPLG_DAPM_CTL_PIN, snd_soc_dapm_get_pin_switch, 160 snd_soc_dapm_put_pin_switch, snd_soc_dapm_info_pin_switch}, 161 }; 162 163 struct soc_tplg_map { 164 int uid; 165 int kid; 166 }; 167 168 /* mapping of widget types from UAPI IDs to kernel IDs */ 169 static const struct soc_tplg_map dapm_map[] = { 170 {SND_SOC_TPLG_DAPM_INPUT, snd_soc_dapm_input}, 171 {SND_SOC_TPLG_DAPM_OUTPUT, snd_soc_dapm_output}, 172 {SND_SOC_TPLG_DAPM_MUX, snd_soc_dapm_mux}, 173 {SND_SOC_TPLG_DAPM_MIXER, snd_soc_dapm_mixer}, 174 {SND_SOC_TPLG_DAPM_PGA, snd_soc_dapm_pga}, 175 {SND_SOC_TPLG_DAPM_OUT_DRV, snd_soc_dapm_out_drv}, 176 {SND_SOC_TPLG_DAPM_ADC, snd_soc_dapm_adc}, 177 {SND_SOC_TPLG_DAPM_DAC, snd_soc_dapm_dac}, 178 {SND_SOC_TPLG_DAPM_SWITCH, snd_soc_dapm_switch}, 179 {SND_SOC_TPLG_DAPM_PRE, snd_soc_dapm_pre}, 180 {SND_SOC_TPLG_DAPM_POST, snd_soc_dapm_post}, 181 {SND_SOC_TPLG_DAPM_AIF_IN, snd_soc_dapm_aif_in}, 182 {SND_SOC_TPLG_DAPM_AIF_OUT, snd_soc_dapm_aif_out}, 183 {SND_SOC_TPLG_DAPM_DAI_IN, snd_soc_dapm_dai_in}, 184 {SND_SOC_TPLG_DAPM_DAI_OUT, snd_soc_dapm_dai_out}, 185 {SND_SOC_TPLG_DAPM_DAI_LINK, snd_soc_dapm_dai_link}, 186 }; 187 188 static int tplc_chan_get_reg(struct soc_tplg *tplg, 189 struct snd_soc_tplg_channel *chan, int map) 190 { 191 int i; 192 193 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) { 194 if (chan[i].id == map) 195 return chan[i].reg; 196 } 197 198 return -EINVAL; 199 } 200 201 static int tplc_chan_get_shift(struct soc_tplg *tplg, 202 struct snd_soc_tplg_channel *chan, int map) 203 { 204 int i; 205 206 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) { 207 if (chan[i].id == map) 208 return chan[i].shift; 209 } 210 211 return -EINVAL; 212 } 213 214 static int get_widget_id(int tplg_type) 215 { 216 int i; 217 218 for (i = 0; i < ARRAY_SIZE(dapm_map); i++) { 219 if (tplg_type == dapm_map[i].uid) 220 return dapm_map[i].kid; 221 } 222 223 return -EINVAL; 224 } 225 226 static enum snd_soc_dobj_type get_dobj_mixer_type( 227 struct snd_soc_tplg_ctl_hdr *control_hdr) 228 { 229 if (control_hdr == NULL) 230 return SND_SOC_DOBJ_NONE; 231 232 switch (control_hdr->ops.info) { 233 case SND_SOC_TPLG_CTL_VOLSW: 234 case SND_SOC_TPLG_CTL_VOLSW_SX: 235 case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 236 case SND_SOC_TPLG_CTL_RANGE: 237 case SND_SOC_TPLG_CTL_STROBE: 238 return SND_SOC_DOBJ_MIXER; 239 case SND_SOC_TPLG_CTL_ENUM: 240 case SND_SOC_TPLG_CTL_ENUM_VALUE: 241 return SND_SOC_DOBJ_ENUM; 242 case SND_SOC_TPLG_CTL_BYTES: 243 return SND_SOC_DOBJ_BYTES; 244 default: 245 return SND_SOC_DOBJ_NONE; 246 } 247 } 248 249 static enum snd_soc_dobj_type get_dobj_type(struct snd_soc_tplg_hdr *hdr, 250 struct snd_soc_tplg_ctl_hdr *control_hdr) 251 { 252 switch (hdr->type) { 253 case SND_SOC_TPLG_TYPE_MIXER: 254 return get_dobj_mixer_type(control_hdr); 255 case SND_SOC_TPLG_TYPE_DAPM_GRAPH: 256 case SND_SOC_TPLG_TYPE_MANIFEST: 257 return SND_SOC_DOBJ_NONE; 258 case SND_SOC_TPLG_TYPE_DAPM_WIDGET: 259 return SND_SOC_DOBJ_WIDGET; 260 case SND_SOC_TPLG_TYPE_DAI_LINK: 261 return SND_SOC_DOBJ_DAI_LINK; 262 case SND_SOC_TPLG_TYPE_PCM: 263 return SND_SOC_DOBJ_PCM; 264 case SND_SOC_TPLG_TYPE_CODEC_LINK: 265 return SND_SOC_DOBJ_CODEC_LINK; 266 default: 267 return SND_SOC_DOBJ_NONE; 268 } 269 } 270 271 static inline void soc_bind_err(struct soc_tplg *tplg, 272 struct snd_soc_tplg_ctl_hdr *hdr, int index) 273 { 274 dev_err(tplg->dev, 275 "ASoC: invalid control type (g,p,i) %d:%d:%d index %d at 0x%lx\n", 276 hdr->ops.get, hdr->ops.put, hdr->ops.info, index, 277 soc_tplg_get_offset(tplg)); 278 } 279 280 static inline void soc_control_err(struct soc_tplg *tplg, 281 struct snd_soc_tplg_ctl_hdr *hdr, const char *name) 282 { 283 dev_err(tplg->dev, 284 "ASoC: no complete mixer IO handler for %s type (g,p,i) %d:%d:%d at 0x%lx\n", 285 name, hdr->ops.get, hdr->ops.put, hdr->ops.info, 286 soc_tplg_get_offset(tplg)); 287 } 288 289 /* pass vendor data to component driver for processing */ 290 static int soc_tplg_vendor_load_(struct soc_tplg *tplg, 291 struct snd_soc_tplg_hdr *hdr) 292 { 293 int ret = 0; 294 295 if (tplg->comp && tplg->ops && tplg->ops->vendor_load) 296 ret = tplg->ops->vendor_load(tplg->comp, hdr); 297 else { 298 dev_err(tplg->dev, "ASoC: no vendor load callback for ID %d\n", 299 hdr->vendor_type); 300 return -EINVAL; 301 } 302 303 if (ret < 0) 304 dev_err(tplg->dev, 305 "ASoC: vendor load failed at hdr offset %ld/0x%lx for type %d:%d\n", 306 soc_tplg_get_hdr_offset(tplg), 307 soc_tplg_get_hdr_offset(tplg), 308 hdr->type, hdr->vendor_type); 309 return ret; 310 } 311 312 /* pass vendor data to component driver for processing */ 313 static int soc_tplg_vendor_load(struct soc_tplg *tplg, 314 struct snd_soc_tplg_hdr *hdr) 315 { 316 if (tplg->pass != SOC_TPLG_PASS_VENDOR) 317 return 0; 318 319 return soc_tplg_vendor_load_(tplg, hdr); 320 } 321 322 /* optionally pass new dynamic widget to component driver. This is mainly for 323 * external widgets where we can assign private data/ops */ 324 static int soc_tplg_widget_load(struct soc_tplg *tplg, 325 struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w) 326 { 327 if (tplg->comp && tplg->ops && tplg->ops->widget_load) 328 return tplg->ops->widget_load(tplg->comp, w, tplg_w); 329 330 return 0; 331 } 332 333 /* pass dynamic FEs configurations to component driver */ 334 static int soc_tplg_pcm_dai_load(struct soc_tplg *tplg, 335 struct snd_soc_tplg_pcm_dai *pcm_dai, int num_pcm_dai) 336 { 337 if (tplg->comp && tplg->ops && tplg->ops->pcm_dai_load) 338 return tplg->ops->pcm_dai_load(tplg->comp, pcm_dai, num_pcm_dai); 339 340 return 0; 341 } 342 343 /* tell the component driver that all firmware has been loaded in this request */ 344 static void soc_tplg_complete(struct soc_tplg *tplg) 345 { 346 if (tplg->comp && tplg->ops && tplg->ops->complete) 347 tplg->ops->complete(tplg->comp); 348 } 349 350 /* add a dynamic kcontrol */ 351 static int soc_tplg_add_dcontrol(struct snd_card *card, struct device *dev, 352 const struct snd_kcontrol_new *control_new, const char *prefix, 353 void *data, struct snd_kcontrol **kcontrol) 354 { 355 int err; 356 357 *kcontrol = snd_soc_cnew(control_new, data, control_new->name, prefix); 358 if (*kcontrol == NULL) { 359 dev_err(dev, "ASoC: Failed to create new kcontrol %s\n", 360 control_new->name); 361 return -ENOMEM; 362 } 363 364 err = snd_ctl_add(card, *kcontrol); 365 if (err < 0) { 366 dev_err(dev, "ASoC: Failed to add %s: %d\n", 367 control_new->name, err); 368 return err; 369 } 370 371 return 0; 372 } 373 374 /* add a dynamic kcontrol for component driver */ 375 static int soc_tplg_add_kcontrol(struct soc_tplg *tplg, 376 struct snd_kcontrol_new *k, struct snd_kcontrol **kcontrol) 377 { 378 struct snd_soc_component *comp = tplg->comp; 379 380 return soc_tplg_add_dcontrol(comp->card->snd_card, 381 comp->dev, k, NULL, comp, kcontrol); 382 } 383 384 /* remove a mixer kcontrol */ 385 static void remove_mixer(struct snd_soc_component *comp, 386 struct snd_soc_dobj *dobj, int pass) 387 { 388 struct snd_card *card = comp->card->snd_card; 389 struct soc_mixer_control *sm = 390 container_of(dobj, struct soc_mixer_control, dobj); 391 const unsigned int *p = NULL; 392 393 if (pass != SOC_TPLG_PASS_MIXER) 394 return; 395 396 if (dobj->ops && dobj->ops->control_unload) 397 dobj->ops->control_unload(comp, dobj); 398 399 if (sm->dobj.control.kcontrol->tlv.p) 400 p = sm->dobj.control.kcontrol->tlv.p; 401 snd_ctl_remove(card, sm->dobj.control.kcontrol); 402 list_del(&sm->dobj.list); 403 kfree(sm); 404 kfree(p); 405 } 406 407 /* remove an enum kcontrol */ 408 static void remove_enum(struct snd_soc_component *comp, 409 struct snd_soc_dobj *dobj, int pass) 410 { 411 struct snd_card *card = comp->card->snd_card; 412 struct soc_enum *se = container_of(dobj, struct soc_enum, dobj); 413 int i; 414 415 if (pass != SOC_TPLG_PASS_MIXER) 416 return; 417 418 if (dobj->ops && dobj->ops->control_unload) 419 dobj->ops->control_unload(comp, dobj); 420 421 snd_ctl_remove(card, se->dobj.control.kcontrol); 422 list_del(&se->dobj.list); 423 424 kfree(se->dobj.control.dvalues); 425 for (i = 0; i < se->items; i++) 426 kfree(se->dobj.control.dtexts[i]); 427 kfree(se); 428 } 429 430 /* remove a byte kcontrol */ 431 static void remove_bytes(struct snd_soc_component *comp, 432 struct snd_soc_dobj *dobj, int pass) 433 { 434 struct snd_card *card = comp->card->snd_card; 435 struct soc_bytes_ext *sb = 436 container_of(dobj, struct soc_bytes_ext, dobj); 437 438 if (pass != SOC_TPLG_PASS_MIXER) 439 return; 440 441 if (dobj->ops && dobj->ops->control_unload) 442 dobj->ops->control_unload(comp, dobj); 443 444 snd_ctl_remove(card, sb->dobj.control.kcontrol); 445 list_del(&sb->dobj.list); 446 kfree(sb); 447 } 448 449 /* remove a widget and it's kcontrols - routes must be removed first */ 450 static void remove_widget(struct snd_soc_component *comp, 451 struct snd_soc_dobj *dobj, int pass) 452 { 453 struct snd_card *card = comp->card->snd_card; 454 struct snd_soc_dapm_widget *w = 455 container_of(dobj, struct snd_soc_dapm_widget, dobj); 456 int i; 457 458 if (pass != SOC_TPLG_PASS_WIDGET) 459 return; 460 461 if (dobj->ops && dobj->ops->widget_unload) 462 dobj->ops->widget_unload(comp, dobj); 463 464 /* 465 * Dynamic Widgets either have 1 enum kcontrol or 1..N mixers. 466 * The enum may either have an array of values or strings. 467 */ 468 if (dobj->widget.kcontrol_enum) { 469 /* enumerated widget mixer */ 470 struct soc_enum *se = 471 (struct soc_enum *)w->kcontrols[0]->private_value; 472 473 snd_ctl_remove(card, w->kcontrols[0]); 474 475 kfree(se->dobj.control.dvalues); 476 for (i = 0; i < se->items; i++) 477 kfree(se->dobj.control.dtexts[i]); 478 479 kfree(se); 480 kfree(w->kcontrol_news); 481 } else { 482 /* non enumerated widget mixer */ 483 for (i = 0; i < w->num_kcontrols; i++) { 484 struct snd_kcontrol *kcontrol = w->kcontrols[i]; 485 struct soc_mixer_control *sm = 486 (struct soc_mixer_control *) kcontrol->private_value; 487 488 kfree(w->kcontrols[i]->tlv.p); 489 490 snd_ctl_remove(card, w->kcontrols[i]); 491 kfree(sm); 492 } 493 kfree(w->kcontrol_news); 494 } 495 /* widget w is freed by soc-dapm.c */ 496 } 497 498 /* remove PCM DAI configurations */ 499 static void remove_pcm_dai(struct snd_soc_component *comp, 500 struct snd_soc_dobj *dobj, int pass) 501 { 502 if (pass != SOC_TPLG_PASS_PCM_DAI) 503 return; 504 505 if (dobj->ops && dobj->ops->pcm_dai_unload) 506 dobj->ops->pcm_dai_unload(comp, dobj); 507 508 list_del(&dobj->list); 509 kfree(dobj); 510 } 511 512 /* bind a kcontrol to it's IO handlers */ 513 static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr, 514 struct snd_kcontrol_new *k, 515 const struct soc_tplg *tplg) 516 { 517 const struct snd_soc_tplg_kcontrol_ops *ops; 518 const struct snd_soc_tplg_bytes_ext_ops *ext_ops; 519 int num_ops, i; 520 521 if (hdr->ops.info == SND_SOC_TPLG_CTL_BYTES 522 && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER 523 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE 524 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 525 struct soc_bytes_ext *sbe; 526 struct snd_soc_tplg_bytes_control *be; 527 528 sbe = (struct soc_bytes_ext *)k->private_value; 529 be = container_of(hdr, struct snd_soc_tplg_bytes_control, hdr); 530 531 /* TLV bytes controls need standard kcontrol info handler, 532 * TLV callback and extended put/get handlers. 533 */ 534 k->info = snd_soc_bytes_info_ext; 535 k->tlv.c = snd_soc_bytes_tlv_callback; 536 537 ext_ops = tplg->bytes_ext_ops; 538 num_ops = tplg->bytes_ext_ops_count; 539 for (i = 0; i < num_ops; i++) { 540 if (!sbe->put && ext_ops[i].id == be->ext_ops.put) 541 sbe->put = ext_ops[i].put; 542 if (!sbe->get && ext_ops[i].id == be->ext_ops.get) 543 sbe->get = ext_ops[i].get; 544 } 545 546 if (sbe->put && sbe->get) 547 return 0; 548 else 549 return -EINVAL; 550 } 551 552 /* try and map vendor specific kcontrol handlers first */ 553 ops = tplg->io_ops; 554 num_ops = tplg->io_ops_count; 555 for (i = 0; i < num_ops; i++) { 556 557 if (k->put == NULL && ops[i].id == hdr->ops.put) 558 k->put = ops[i].put; 559 if (k->get == NULL && ops[i].id == hdr->ops.get) 560 k->get = ops[i].get; 561 if (k->info == NULL && ops[i].id == hdr->ops.info) 562 k->info = ops[i].info; 563 } 564 565 /* vendor specific handlers found ? */ 566 if (k->put && k->get && k->info) 567 return 0; 568 569 /* none found so try standard kcontrol handlers */ 570 ops = io_ops; 571 num_ops = ARRAY_SIZE(io_ops); 572 for (i = 0; i < num_ops; i++) { 573 574 if (k->put == NULL && ops[i].id == hdr->ops.put) 575 k->put = ops[i].put; 576 if (k->get == NULL && ops[i].id == hdr->ops.get) 577 k->get = ops[i].get; 578 if (k->info == NULL && ops[i].id == hdr->ops.info) 579 k->info = ops[i].info; 580 } 581 582 /* standard handlers found ? */ 583 if (k->put && k->get && k->info) 584 return 0; 585 586 /* nothing to bind */ 587 return -EINVAL; 588 } 589 590 /* bind a widgets to it's evnt handlers */ 591 int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w, 592 const struct snd_soc_tplg_widget_events *events, 593 int num_events, u16 event_type) 594 { 595 int i; 596 597 w->event = NULL; 598 599 for (i = 0; i < num_events; i++) { 600 if (event_type == events[i].type) { 601 602 /* found - so assign event */ 603 w->event = events[i].event_handler; 604 return 0; 605 } 606 } 607 608 /* not found */ 609 return -EINVAL; 610 } 611 EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_bind_event); 612 613 /* optionally pass new dynamic kcontrol to component driver. */ 614 static int soc_tplg_init_kcontrol(struct soc_tplg *tplg, 615 struct snd_kcontrol_new *k, struct snd_soc_tplg_ctl_hdr *hdr) 616 { 617 if (tplg->comp && tplg->ops && tplg->ops->control_load) 618 return tplg->ops->control_load(tplg->comp, k, hdr); 619 620 return 0; 621 } 622 623 624 static int soc_tplg_create_tlv_db_scale(struct soc_tplg *tplg, 625 struct snd_kcontrol_new *kc, struct snd_soc_tplg_tlv_dbscale *scale) 626 { 627 unsigned int item_len = 2 * sizeof(unsigned int); 628 unsigned int *p; 629 630 p = kzalloc(item_len + 2 * sizeof(unsigned int), GFP_KERNEL); 631 if (!p) 632 return -ENOMEM; 633 634 p[0] = SNDRV_CTL_TLVT_DB_SCALE; 635 p[1] = item_len; 636 p[2] = scale->min; 637 p[3] = (scale->step & TLV_DB_SCALE_MASK) 638 | (scale->mute ? TLV_DB_SCALE_MUTE : 0); 639 640 kc->tlv.p = (void *)p; 641 return 0; 642 } 643 644 static int soc_tplg_create_tlv(struct soc_tplg *tplg, 645 struct snd_kcontrol_new *kc, struct snd_soc_tplg_ctl_hdr *tc) 646 { 647 struct snd_soc_tplg_ctl_tlv *tplg_tlv; 648 649 if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)) 650 return 0; 651 652 if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) { 653 tplg_tlv = &tc->tlv; 654 switch (tplg_tlv->type) { 655 case SNDRV_CTL_TLVT_DB_SCALE: 656 return soc_tplg_create_tlv_db_scale(tplg, kc, 657 &tplg_tlv->scale); 658 659 /* TODO: add support for other TLV types */ 660 default: 661 dev_dbg(tplg->dev, "Unsupported TLV type %d\n", 662 tplg_tlv->type); 663 return -EINVAL; 664 } 665 } 666 667 return 0; 668 } 669 670 static inline void soc_tplg_free_tlv(struct soc_tplg *tplg, 671 struct snd_kcontrol_new *kc) 672 { 673 kfree(kc->tlv.p); 674 } 675 676 static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, 677 size_t size) 678 { 679 struct snd_soc_tplg_bytes_control *be; 680 struct soc_bytes_ext *sbe; 681 struct snd_kcontrol_new kc; 682 int i, err; 683 684 if (soc_tplg_check_elem_count(tplg, 685 sizeof(struct snd_soc_tplg_bytes_control), count, 686 size, "mixer bytes")) { 687 dev_err(tplg->dev, "ASoC: Invalid count %d for byte control\n", 688 count); 689 return -EINVAL; 690 } 691 692 for (i = 0; i < count; i++) { 693 be = (struct snd_soc_tplg_bytes_control *)tplg->pos; 694 695 /* validate kcontrol */ 696 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 697 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 698 return -EINVAL; 699 700 sbe = kzalloc(sizeof(*sbe), GFP_KERNEL); 701 if (sbe == NULL) 702 return -ENOMEM; 703 704 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + 705 be->priv.size); 706 707 dev_dbg(tplg->dev, 708 "ASoC: adding bytes kcontrol %s with access 0x%x\n", 709 be->hdr.name, be->hdr.access); 710 711 memset(&kc, 0, sizeof(kc)); 712 kc.name = be->hdr.name; 713 kc.private_value = (long)sbe; 714 kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 715 kc.access = be->hdr.access; 716 717 sbe->max = be->max; 718 sbe->dobj.type = SND_SOC_DOBJ_BYTES; 719 sbe->dobj.ops = tplg->ops; 720 INIT_LIST_HEAD(&sbe->dobj.list); 721 722 /* map io handlers */ 723 err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, tplg); 724 if (err) { 725 soc_control_err(tplg, &be->hdr, be->hdr.name); 726 kfree(sbe); 727 continue; 728 } 729 730 /* pass control to driver for optional further init */ 731 err = soc_tplg_init_kcontrol(tplg, &kc, 732 (struct snd_soc_tplg_ctl_hdr *)be); 733 if (err < 0) { 734 dev_err(tplg->dev, "ASoC: failed to init %s\n", 735 be->hdr.name); 736 kfree(sbe); 737 continue; 738 } 739 740 /* register control here */ 741 err = soc_tplg_add_kcontrol(tplg, &kc, 742 &sbe->dobj.control.kcontrol); 743 if (err < 0) { 744 dev_err(tplg->dev, "ASoC: failed to add %s\n", 745 be->hdr.name); 746 kfree(sbe); 747 continue; 748 } 749 750 list_add(&sbe->dobj.list, &tplg->comp->dobj_list); 751 } 752 return 0; 753 754 } 755 756 static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, 757 size_t size) 758 { 759 struct snd_soc_tplg_mixer_control *mc; 760 struct soc_mixer_control *sm; 761 struct snd_kcontrol_new kc; 762 int i, err; 763 764 if (soc_tplg_check_elem_count(tplg, 765 sizeof(struct snd_soc_tplg_mixer_control), 766 count, size, "mixers")) { 767 768 dev_err(tplg->dev, "ASoC: invalid count %d for controls\n", 769 count); 770 return -EINVAL; 771 } 772 773 for (i = 0; i < count; i++) { 774 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; 775 776 /* validate kcontrol */ 777 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 778 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 779 return -EINVAL; 780 781 sm = kzalloc(sizeof(*sm), GFP_KERNEL); 782 if (sm == NULL) 783 return -ENOMEM; 784 tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + 785 mc->priv.size); 786 787 dev_dbg(tplg->dev, 788 "ASoC: adding mixer kcontrol %s with access 0x%x\n", 789 mc->hdr.name, mc->hdr.access); 790 791 memset(&kc, 0, sizeof(kc)); 792 kc.name = mc->hdr.name; 793 kc.private_value = (long)sm; 794 kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 795 kc.access = mc->hdr.access; 796 797 /* we only support FL/FR channel mapping atm */ 798 sm->reg = tplc_chan_get_reg(tplg, mc->channel, 799 SNDRV_CHMAP_FL); 800 sm->rreg = tplc_chan_get_reg(tplg, mc->channel, 801 SNDRV_CHMAP_FR); 802 sm->shift = tplc_chan_get_shift(tplg, mc->channel, 803 SNDRV_CHMAP_FL); 804 sm->rshift = tplc_chan_get_shift(tplg, mc->channel, 805 SNDRV_CHMAP_FR); 806 807 sm->max = mc->max; 808 sm->min = mc->min; 809 sm->invert = mc->invert; 810 sm->platform_max = mc->platform_max; 811 sm->dobj.index = tplg->index; 812 sm->dobj.ops = tplg->ops; 813 sm->dobj.type = SND_SOC_DOBJ_MIXER; 814 INIT_LIST_HEAD(&sm->dobj.list); 815 816 /* map io handlers */ 817 err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, tplg); 818 if (err) { 819 soc_control_err(tplg, &mc->hdr, mc->hdr.name); 820 kfree(sm); 821 continue; 822 } 823 824 /* pass control to driver for optional further init */ 825 err = soc_tplg_init_kcontrol(tplg, &kc, 826 (struct snd_soc_tplg_ctl_hdr *) mc); 827 if (err < 0) { 828 dev_err(tplg->dev, "ASoC: failed to init %s\n", 829 mc->hdr.name); 830 kfree(sm); 831 continue; 832 } 833 834 /* create any TLV data */ 835 soc_tplg_create_tlv(tplg, &kc, &mc->hdr); 836 837 /* register control here */ 838 err = soc_tplg_add_kcontrol(tplg, &kc, 839 &sm->dobj.control.kcontrol); 840 if (err < 0) { 841 dev_err(tplg->dev, "ASoC: failed to add %s\n", 842 mc->hdr.name); 843 soc_tplg_free_tlv(tplg, &kc); 844 kfree(sm); 845 continue; 846 } 847 848 list_add(&sm->dobj.list, &tplg->comp->dobj_list); 849 } 850 851 return 0; 852 } 853 854 static int soc_tplg_denum_create_texts(struct soc_enum *se, 855 struct snd_soc_tplg_enum_control *ec) 856 { 857 int i, ret; 858 859 se->dobj.control.dtexts = 860 kzalloc(sizeof(char *) * ec->items, GFP_KERNEL); 861 if (se->dobj.control.dtexts == NULL) 862 return -ENOMEM; 863 864 for (i = 0; i < ec->items; i++) { 865 866 if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 867 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) { 868 ret = -EINVAL; 869 goto err; 870 } 871 872 se->dobj.control.dtexts[i] = kstrdup(ec->texts[i], GFP_KERNEL); 873 if (!se->dobj.control.dtexts[i]) { 874 ret = -ENOMEM; 875 goto err; 876 } 877 } 878 879 return 0; 880 881 err: 882 for (--i; i >= 0; i--) 883 kfree(se->dobj.control.dtexts[i]); 884 kfree(se->dobj.control.dtexts); 885 return ret; 886 } 887 888 static int soc_tplg_denum_create_values(struct soc_enum *se, 889 struct snd_soc_tplg_enum_control *ec) 890 { 891 if (ec->items > sizeof(*ec->values)) 892 return -EINVAL; 893 894 se->dobj.control.dvalues = kmemdup(ec->values, 895 ec->items * sizeof(u32), 896 GFP_KERNEL); 897 if (!se->dobj.control.dvalues) 898 return -ENOMEM; 899 900 return 0; 901 } 902 903 static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, 904 size_t size) 905 { 906 struct snd_soc_tplg_enum_control *ec; 907 struct soc_enum *se; 908 struct snd_kcontrol_new kc; 909 int i, ret, err; 910 911 if (soc_tplg_check_elem_count(tplg, 912 sizeof(struct snd_soc_tplg_enum_control), 913 count, size, "enums")) { 914 915 dev_err(tplg->dev, "ASoC: invalid count %d for enum controls\n", 916 count); 917 return -EINVAL; 918 } 919 920 for (i = 0; i < count; i++) { 921 ec = (struct snd_soc_tplg_enum_control *)tplg->pos; 922 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + 923 ec->priv.size); 924 925 /* validate kcontrol */ 926 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 927 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 928 return -EINVAL; 929 930 se = kzalloc((sizeof(*se)), GFP_KERNEL); 931 if (se == NULL) 932 return -ENOMEM; 933 934 dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", 935 ec->hdr.name, ec->items); 936 937 memset(&kc, 0, sizeof(kc)); 938 kc.name = ec->hdr.name; 939 kc.private_value = (long)se; 940 kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 941 kc.access = ec->hdr.access; 942 943 se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); 944 se->shift_l = tplc_chan_get_shift(tplg, ec->channel, 945 SNDRV_CHMAP_FL); 946 se->shift_r = tplc_chan_get_shift(tplg, ec->channel, 947 SNDRV_CHMAP_FL); 948 949 se->items = ec->items; 950 se->mask = ec->mask; 951 se->dobj.index = tplg->index; 952 se->dobj.type = SND_SOC_DOBJ_ENUM; 953 se->dobj.ops = tplg->ops; 954 INIT_LIST_HEAD(&se->dobj.list); 955 956 switch (ec->hdr.ops.info) { 957 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: 958 case SND_SOC_TPLG_CTL_ENUM_VALUE: 959 err = soc_tplg_denum_create_values(se, ec); 960 if (err < 0) { 961 dev_err(tplg->dev, 962 "ASoC: could not create values for %s\n", 963 ec->hdr.name); 964 kfree(se); 965 continue; 966 } 967 /* fall through and create texts */ 968 case SND_SOC_TPLG_CTL_ENUM: 969 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: 970 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: 971 err = soc_tplg_denum_create_texts(se, ec); 972 if (err < 0) { 973 dev_err(tplg->dev, 974 "ASoC: could not create texts for %s\n", 975 ec->hdr.name); 976 kfree(se); 977 continue; 978 } 979 break; 980 default: 981 dev_err(tplg->dev, 982 "ASoC: invalid enum control type %d for %s\n", 983 ec->hdr.ops.info, ec->hdr.name); 984 kfree(se); 985 continue; 986 } 987 988 /* map io handlers */ 989 err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg); 990 if (err) { 991 soc_control_err(tplg, &ec->hdr, ec->hdr.name); 992 kfree(se); 993 continue; 994 } 995 996 /* pass control to driver for optional further init */ 997 err = soc_tplg_init_kcontrol(tplg, &kc, 998 (struct snd_soc_tplg_ctl_hdr *) ec); 999 if (err < 0) { 1000 dev_err(tplg->dev, "ASoC: failed to init %s\n", 1001 ec->hdr.name); 1002 kfree(se); 1003 continue; 1004 } 1005 1006 /* register control here */ 1007 ret = soc_tplg_add_kcontrol(tplg, 1008 &kc, &se->dobj.control.kcontrol); 1009 if (ret < 0) { 1010 dev_err(tplg->dev, "ASoC: could not add kcontrol %s\n", 1011 ec->hdr.name); 1012 kfree(se); 1013 continue; 1014 } 1015 1016 list_add(&se->dobj.list, &tplg->comp->dobj_list); 1017 } 1018 1019 return 0; 1020 } 1021 1022 static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, 1023 struct snd_soc_tplg_hdr *hdr) 1024 { 1025 struct snd_soc_tplg_ctl_hdr *control_hdr; 1026 int i; 1027 1028 if (tplg->pass != SOC_TPLG_PASS_MIXER) { 1029 tplg->pos += hdr->size + hdr->payload_size; 1030 return 0; 1031 } 1032 1033 dev_dbg(tplg->dev, "ASoC: adding %d kcontrols at 0x%lx\n", hdr->count, 1034 soc_tplg_get_offset(tplg)); 1035 1036 for (i = 0; i < hdr->count; i++) { 1037 1038 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; 1039 1040 switch (control_hdr->ops.info) { 1041 case SND_SOC_TPLG_CTL_VOLSW: 1042 case SND_SOC_TPLG_CTL_STROBE: 1043 case SND_SOC_TPLG_CTL_VOLSW_SX: 1044 case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 1045 case SND_SOC_TPLG_CTL_RANGE: 1046 case SND_SOC_TPLG_DAPM_CTL_VOLSW: 1047 case SND_SOC_TPLG_DAPM_CTL_PIN: 1048 soc_tplg_dmixer_create(tplg, 1, hdr->payload_size); 1049 break; 1050 case SND_SOC_TPLG_CTL_ENUM: 1051 case SND_SOC_TPLG_CTL_ENUM_VALUE: 1052 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: 1053 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: 1054 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: 1055 soc_tplg_denum_create(tplg, 1, hdr->payload_size); 1056 break; 1057 case SND_SOC_TPLG_CTL_BYTES: 1058 soc_tplg_dbytes_create(tplg, 1, hdr->payload_size); 1059 break; 1060 default: 1061 soc_bind_err(tplg, control_hdr, i); 1062 return -EINVAL; 1063 } 1064 } 1065 1066 return 0; 1067 } 1068 1069 static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, 1070 struct snd_soc_tplg_hdr *hdr) 1071 { 1072 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; 1073 struct snd_soc_dapm_route route; 1074 struct snd_soc_tplg_dapm_graph_elem *elem; 1075 int count = hdr->count, i; 1076 1077 if (tplg->pass != SOC_TPLG_PASS_GRAPH) { 1078 tplg->pos += hdr->size + hdr->payload_size; 1079 return 0; 1080 } 1081 1082 if (soc_tplg_check_elem_count(tplg, 1083 sizeof(struct snd_soc_tplg_dapm_graph_elem), 1084 count, hdr->payload_size, "graph")) { 1085 1086 dev_err(tplg->dev, "ASoC: invalid count %d for DAPM routes\n", 1087 count); 1088 return -EINVAL; 1089 } 1090 1091 dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes\n", count); 1092 1093 for (i = 0; i < count; i++) { 1094 elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos; 1095 tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem); 1096 1097 /* validate routes */ 1098 if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1099 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1100 return -EINVAL; 1101 if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1102 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1103 return -EINVAL; 1104 if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1105 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1106 return -EINVAL; 1107 1108 route.source = elem->source; 1109 route.sink = elem->sink; 1110 route.connected = NULL; /* set to NULL atm for tplg users */ 1111 if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0) 1112 route.control = NULL; 1113 else 1114 route.control = elem->control; 1115 1116 /* add route, but keep going if some fail */ 1117 snd_soc_dapm_add_routes(dapm, &route, 1); 1118 } 1119 1120 return 0; 1121 } 1122 1123 static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( 1124 struct soc_tplg *tplg, int num_kcontrols) 1125 { 1126 struct snd_kcontrol_new *kc; 1127 struct soc_mixer_control *sm; 1128 struct snd_soc_tplg_mixer_control *mc; 1129 int i, err; 1130 1131 kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL); 1132 if (kc == NULL) 1133 return NULL; 1134 1135 for (i = 0; i < num_kcontrols; i++) { 1136 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; 1137 sm = kzalloc(sizeof(*sm), GFP_KERNEL); 1138 if (sm == NULL) 1139 goto err; 1140 1141 tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + 1142 mc->priv.size); 1143 1144 /* validate kcontrol */ 1145 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1146 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1147 goto err_str; 1148 1149 dev_dbg(tplg->dev, " adding DAPM widget mixer control %s at %d\n", 1150 mc->hdr.name, i); 1151 1152 kc[i].name = mc->hdr.name; 1153 kc[i].private_value = (long)sm; 1154 kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1155 kc[i].access = mc->hdr.access; 1156 1157 /* we only support FL/FR channel mapping atm */ 1158 sm->reg = tplc_chan_get_reg(tplg, mc->channel, 1159 SNDRV_CHMAP_FL); 1160 sm->rreg = tplc_chan_get_reg(tplg, mc->channel, 1161 SNDRV_CHMAP_FR); 1162 sm->shift = tplc_chan_get_shift(tplg, mc->channel, 1163 SNDRV_CHMAP_FL); 1164 sm->rshift = tplc_chan_get_shift(tplg, mc->channel, 1165 SNDRV_CHMAP_FR); 1166 1167 sm->max = mc->max; 1168 sm->min = mc->min; 1169 sm->invert = mc->invert; 1170 sm->platform_max = mc->platform_max; 1171 sm->dobj.index = tplg->index; 1172 INIT_LIST_HEAD(&sm->dobj.list); 1173 1174 /* map io handlers */ 1175 err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc[i], tplg); 1176 if (err) { 1177 soc_control_err(tplg, &mc->hdr, mc->hdr.name); 1178 kfree(sm); 1179 continue; 1180 } 1181 1182 /* pass control to driver for optional further init */ 1183 err = soc_tplg_init_kcontrol(tplg, &kc[i], 1184 (struct snd_soc_tplg_ctl_hdr *)mc); 1185 if (err < 0) { 1186 dev_err(tplg->dev, "ASoC: failed to init %s\n", 1187 mc->hdr.name); 1188 kfree(sm); 1189 continue; 1190 } 1191 } 1192 return kc; 1193 1194 err_str: 1195 kfree(sm); 1196 err: 1197 for (--i; i >= 0; i--) 1198 kfree((void *)kc[i].private_value); 1199 kfree(kc); 1200 return NULL; 1201 } 1202 1203 static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( 1204 struct soc_tplg *tplg) 1205 { 1206 struct snd_kcontrol_new *kc; 1207 struct snd_soc_tplg_enum_control *ec; 1208 struct soc_enum *se; 1209 int i, err; 1210 1211 ec = (struct snd_soc_tplg_enum_control *)tplg->pos; 1212 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + 1213 ec->priv.size); 1214 1215 /* validate kcontrol */ 1216 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1217 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1218 return NULL; 1219 1220 kc = kzalloc(sizeof(*kc), GFP_KERNEL); 1221 if (kc == NULL) 1222 return NULL; 1223 1224 se = kzalloc(sizeof(*se), GFP_KERNEL); 1225 if (se == NULL) 1226 goto err; 1227 1228 dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n", 1229 ec->hdr.name); 1230 1231 kc->name = ec->hdr.name; 1232 kc->private_value = (long)se; 1233 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1234 kc->access = ec->hdr.access; 1235 1236 /* we only support FL/FR channel mapping atm */ 1237 se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); 1238 se->shift_l = tplc_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); 1239 se->shift_r = tplc_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR); 1240 1241 se->items = ec->items; 1242 se->mask = ec->mask; 1243 se->dobj.index = tplg->index; 1244 1245 switch (ec->hdr.ops.info) { 1246 case SND_SOC_TPLG_CTL_ENUM_VALUE: 1247 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: 1248 err = soc_tplg_denum_create_values(se, ec); 1249 if (err < 0) { 1250 dev_err(tplg->dev, "ASoC: could not create values for %s\n", 1251 ec->hdr.name); 1252 goto err_se; 1253 } 1254 /* fall through to create texts */ 1255 case SND_SOC_TPLG_CTL_ENUM: 1256 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: 1257 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: 1258 err = soc_tplg_denum_create_texts(se, ec); 1259 if (err < 0) { 1260 dev_err(tplg->dev, "ASoC: could not create texts for %s\n", 1261 ec->hdr.name); 1262 goto err_se; 1263 } 1264 break; 1265 default: 1266 dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", 1267 ec->hdr.ops.info, ec->hdr.name); 1268 goto err_se; 1269 } 1270 1271 /* map io handlers */ 1272 err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg); 1273 if (err) { 1274 soc_control_err(tplg, &ec->hdr, ec->hdr.name); 1275 goto err_se; 1276 } 1277 1278 /* pass control to driver for optional further init */ 1279 err = soc_tplg_init_kcontrol(tplg, kc, 1280 (struct snd_soc_tplg_ctl_hdr *)ec); 1281 if (err < 0) { 1282 dev_err(tplg->dev, "ASoC: failed to init %s\n", 1283 ec->hdr.name); 1284 goto err_se; 1285 } 1286 1287 return kc; 1288 1289 err_se: 1290 /* free values and texts */ 1291 kfree(se->dobj.control.dvalues); 1292 for (i = 0; i < ec->items; i++) 1293 kfree(se->dobj.control.dtexts[i]); 1294 1295 kfree(se); 1296 err: 1297 kfree(kc); 1298 1299 return NULL; 1300 } 1301 1302 static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( 1303 struct soc_tplg *tplg, int count) 1304 { 1305 struct snd_soc_tplg_bytes_control *be; 1306 struct soc_bytes_ext *sbe; 1307 struct snd_kcontrol_new *kc; 1308 int i, err; 1309 1310 kc = kcalloc(count, sizeof(*kc), GFP_KERNEL); 1311 if (!kc) 1312 return NULL; 1313 1314 for (i = 0; i < count; i++) { 1315 be = (struct snd_soc_tplg_bytes_control *)tplg->pos; 1316 1317 /* validate kcontrol */ 1318 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1319 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1320 goto err; 1321 1322 sbe = kzalloc(sizeof(*sbe), GFP_KERNEL); 1323 if (sbe == NULL) 1324 goto err; 1325 1326 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + 1327 be->priv.size); 1328 1329 dev_dbg(tplg->dev, 1330 "ASoC: adding bytes kcontrol %s with access 0x%x\n", 1331 be->hdr.name, be->hdr.access); 1332 1333 kc[i].name = be->hdr.name; 1334 kc[i].private_value = (long)sbe; 1335 kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1336 kc[i].access = be->hdr.access; 1337 1338 sbe->max = be->max; 1339 INIT_LIST_HEAD(&sbe->dobj.list); 1340 1341 /* map standard io handlers and check for external handlers */ 1342 err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc[i], tplg); 1343 if (err) { 1344 soc_control_err(tplg, &be->hdr, be->hdr.name); 1345 kfree(sbe); 1346 continue; 1347 } 1348 1349 /* pass control to driver for optional further init */ 1350 err = soc_tplg_init_kcontrol(tplg, &kc[i], 1351 (struct snd_soc_tplg_ctl_hdr *)be); 1352 if (err < 0) { 1353 dev_err(tplg->dev, "ASoC: failed to init %s\n", 1354 be->hdr.name); 1355 kfree(sbe); 1356 continue; 1357 } 1358 } 1359 1360 return kc; 1361 1362 err: 1363 for (--i; i >= 0; i--) 1364 kfree((void *)kc[i].private_value); 1365 1366 kfree(kc); 1367 return NULL; 1368 } 1369 1370 static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, 1371 struct snd_soc_tplg_dapm_widget *w) 1372 { 1373 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; 1374 struct snd_soc_dapm_widget template, *widget; 1375 struct snd_soc_tplg_ctl_hdr *control_hdr; 1376 struct snd_soc_card *card = tplg->comp->card; 1377 int ret = 0; 1378 1379 if (strnlen(w->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1380 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1381 return -EINVAL; 1382 if (strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1383 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1384 return -EINVAL; 1385 1386 dev_dbg(tplg->dev, "ASoC: creating DAPM widget %s id %d\n", 1387 w->name, w->id); 1388 1389 memset(&template, 0, sizeof(template)); 1390 1391 /* map user to kernel widget ID */ 1392 template.id = get_widget_id(w->id); 1393 if (template.id < 0) 1394 return template.id; 1395 1396 template.name = kstrdup(w->name, GFP_KERNEL); 1397 if (!template.name) 1398 return -ENOMEM; 1399 template.sname = kstrdup(w->sname, GFP_KERNEL); 1400 if (!template.sname) { 1401 ret = -ENOMEM; 1402 goto err; 1403 } 1404 template.reg = w->reg; 1405 template.shift = w->shift; 1406 template.mask = w->mask; 1407 template.subseq = w->subseq; 1408 template.on_val = w->invert ? 0 : 1; 1409 template.off_val = w->invert ? 1 : 0; 1410 template.ignore_suspend = w->ignore_suspend; 1411 template.event_flags = w->event_flags; 1412 template.dobj.index = tplg->index; 1413 1414 tplg->pos += 1415 (sizeof(struct snd_soc_tplg_dapm_widget) + w->priv.size); 1416 if (w->num_kcontrols == 0) { 1417 template.num_kcontrols = 0; 1418 goto widget; 1419 } 1420 1421 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; 1422 dev_dbg(tplg->dev, "ASoC: template %s has %d controls of type %x\n", 1423 w->name, w->num_kcontrols, control_hdr->type); 1424 1425 switch (control_hdr->ops.info) { 1426 case SND_SOC_TPLG_CTL_VOLSW: 1427 case SND_SOC_TPLG_CTL_STROBE: 1428 case SND_SOC_TPLG_CTL_VOLSW_SX: 1429 case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 1430 case SND_SOC_TPLG_CTL_RANGE: 1431 case SND_SOC_TPLG_DAPM_CTL_VOLSW: 1432 template.num_kcontrols = w->num_kcontrols; 1433 template.kcontrol_news = 1434 soc_tplg_dapm_widget_dmixer_create(tplg, 1435 template.num_kcontrols); 1436 if (!template.kcontrol_news) { 1437 ret = -ENOMEM; 1438 goto hdr_err; 1439 } 1440 break; 1441 case SND_SOC_TPLG_CTL_ENUM: 1442 case SND_SOC_TPLG_CTL_ENUM_VALUE: 1443 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: 1444 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: 1445 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: 1446 template.dobj.widget.kcontrol_enum = 1; 1447 template.num_kcontrols = 1; 1448 template.kcontrol_news = 1449 soc_tplg_dapm_widget_denum_create(tplg); 1450 if (!template.kcontrol_news) { 1451 ret = -ENOMEM; 1452 goto hdr_err; 1453 } 1454 break; 1455 case SND_SOC_TPLG_CTL_BYTES: 1456 template.num_kcontrols = w->num_kcontrols; 1457 template.kcontrol_news = 1458 soc_tplg_dapm_widget_dbytes_create(tplg, 1459 template.num_kcontrols); 1460 if (!template.kcontrol_news) { 1461 ret = -ENOMEM; 1462 goto hdr_err; 1463 } 1464 break; 1465 default: 1466 dev_err(tplg->dev, "ASoC: invalid widget control type %d:%d:%d\n", 1467 control_hdr->ops.get, control_hdr->ops.put, 1468 control_hdr->ops.info); 1469 ret = -EINVAL; 1470 goto hdr_err; 1471 } 1472 1473 widget: 1474 ret = soc_tplg_widget_load(tplg, &template, w); 1475 if (ret < 0) 1476 goto hdr_err; 1477 1478 /* card dapm mutex is held by the core if we are loading topology 1479 * data during sound card init. */ 1480 if (card->instantiated) 1481 widget = snd_soc_dapm_new_control(dapm, &template); 1482 else 1483 widget = snd_soc_dapm_new_control_unlocked(dapm, &template); 1484 if (widget == NULL) { 1485 dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n", 1486 w->name); 1487 goto hdr_err; 1488 } 1489 1490 widget->dobj.type = SND_SOC_DOBJ_WIDGET; 1491 widget->dobj.ops = tplg->ops; 1492 widget->dobj.index = tplg->index; 1493 list_add(&widget->dobj.list, &tplg->comp->dobj_list); 1494 return 0; 1495 1496 hdr_err: 1497 kfree(template.sname); 1498 err: 1499 kfree(template.name); 1500 return ret; 1501 } 1502 1503 static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg, 1504 struct snd_soc_tplg_hdr *hdr) 1505 { 1506 struct snd_soc_tplg_dapm_widget *widget; 1507 int ret, count = hdr->count, i; 1508 1509 if (tplg->pass != SOC_TPLG_PASS_WIDGET) 1510 return 0; 1511 1512 dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count); 1513 1514 for (i = 0; i < count; i++) { 1515 widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; 1516 ret = soc_tplg_dapm_widget_create(tplg, widget); 1517 if (ret < 0) 1518 dev_err(tplg->dev, "ASoC: failed to load widget %s\n", 1519 widget->name); 1520 } 1521 1522 return 0; 1523 } 1524 1525 static int soc_tplg_dapm_complete(struct soc_tplg *tplg) 1526 { 1527 struct snd_soc_card *card = tplg->comp->card; 1528 int ret; 1529 1530 /* Card might not have been registered at this point. 1531 * If so, just return success. 1532 */ 1533 if (!card || !card->instantiated) { 1534 dev_warn(tplg->dev, "ASoC: Parent card not yet available," 1535 "Do not add new widgets now\n"); 1536 return 0; 1537 } 1538 1539 ret = snd_soc_dapm_new_widgets(card); 1540 if (ret < 0) 1541 dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n", 1542 ret); 1543 1544 return 0; 1545 } 1546 1547 static int soc_tplg_pcm_dai_elems_load(struct soc_tplg *tplg, 1548 struct snd_soc_tplg_hdr *hdr) 1549 { 1550 struct snd_soc_tplg_pcm_dai *pcm_dai; 1551 struct snd_soc_dobj *dobj; 1552 int count = hdr->count; 1553 int ret; 1554 1555 if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) 1556 return 0; 1557 1558 pcm_dai = (struct snd_soc_tplg_pcm_dai *)tplg->pos; 1559 1560 if (soc_tplg_check_elem_count(tplg, 1561 sizeof(struct snd_soc_tplg_pcm), count, 1562 hdr->payload_size, "PCM DAI")) { 1563 dev_err(tplg->dev, "ASoC: invalid count %d for PCM DAI elems\n", 1564 count); 1565 return -EINVAL; 1566 } 1567 1568 dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count); 1569 tplg->pos += sizeof(struct snd_soc_tplg_pcm) * count; 1570 1571 dobj = kzalloc(sizeof(struct snd_soc_dobj), GFP_KERNEL); 1572 if (dobj == NULL) 1573 return -ENOMEM; 1574 1575 /* Call the platform driver call back to register the dais */ 1576 ret = soc_tplg_pcm_dai_load(tplg, pcm_dai, count); 1577 if (ret < 0) { 1578 dev_err(tplg->comp->dev, "ASoC: PCM DAI loading failed\n"); 1579 goto err; 1580 } 1581 1582 dobj->type = get_dobj_type(hdr, NULL); 1583 dobj->pcm_dai.count = count; 1584 dobj->pcm_dai.pd = pcm_dai; 1585 dobj->ops = tplg->ops; 1586 dobj->index = tplg->index; 1587 list_add(&dobj->list, &tplg->comp->dobj_list); 1588 return 0; 1589 1590 err: 1591 kfree(dobj); 1592 return ret; 1593 } 1594 1595 static int soc_tplg_manifest_load(struct soc_tplg *tplg, 1596 struct snd_soc_tplg_hdr *hdr) 1597 { 1598 struct snd_soc_tplg_manifest *manifest; 1599 1600 if (tplg->pass != SOC_TPLG_PASS_MANIFEST) 1601 return 0; 1602 1603 manifest = (struct snd_soc_tplg_manifest *)tplg->pos; 1604 tplg->pos += sizeof(struct snd_soc_tplg_manifest); 1605 1606 if (tplg->comp && tplg->ops && tplg->ops->manifest) 1607 return tplg->ops->manifest(tplg->comp, manifest); 1608 1609 dev_err(tplg->dev, "ASoC: Firmware manifest not supported\n"); 1610 return 0; 1611 } 1612 1613 /* validate header magic, size and type */ 1614 static int soc_valid_header(struct soc_tplg *tplg, 1615 struct snd_soc_tplg_hdr *hdr) 1616 { 1617 if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) 1618 return 0; 1619 1620 /* big endian firmware objects not supported atm */ 1621 if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) { 1622 dev_err(tplg->dev, 1623 "ASoC: pass %d big endian not supported header got %x at offset 0x%lx size 0x%zx.\n", 1624 tplg->pass, hdr->magic, 1625 soc_tplg_get_hdr_offset(tplg), tplg->fw->size); 1626 return -EINVAL; 1627 } 1628 1629 if (hdr->magic != SND_SOC_TPLG_MAGIC) { 1630 dev_err(tplg->dev, 1631 "ASoC: pass %d does not have a valid header got %x at offset 0x%lx size 0x%zx.\n", 1632 tplg->pass, hdr->magic, 1633 soc_tplg_get_hdr_offset(tplg), tplg->fw->size); 1634 return -EINVAL; 1635 } 1636 1637 if (hdr->abi != SND_SOC_TPLG_ABI_VERSION) { 1638 dev_err(tplg->dev, 1639 "ASoC: pass %d invalid ABI version got 0x%x need 0x%x at offset 0x%lx size 0x%zx.\n", 1640 tplg->pass, hdr->abi, 1641 SND_SOC_TPLG_ABI_VERSION, soc_tplg_get_hdr_offset(tplg), 1642 tplg->fw->size); 1643 return -EINVAL; 1644 } 1645 1646 if (hdr->payload_size == 0) { 1647 dev_err(tplg->dev, "ASoC: header has 0 size at offset 0x%lx.\n", 1648 soc_tplg_get_hdr_offset(tplg)); 1649 return -EINVAL; 1650 } 1651 1652 if (tplg->pass == hdr->type) 1653 dev_dbg(tplg->dev, 1654 "ASoC: Got 0x%x bytes of type %d version %d vendor %d at pass %d\n", 1655 hdr->payload_size, hdr->type, hdr->version, 1656 hdr->vendor_type, tplg->pass); 1657 1658 return 1; 1659 } 1660 1661 /* check header type and call appropriate handler */ 1662 static int soc_tplg_load_header(struct soc_tplg *tplg, 1663 struct snd_soc_tplg_hdr *hdr) 1664 { 1665 tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr); 1666 1667 /* check for matching ID */ 1668 if (hdr->index != tplg->req_index && 1669 hdr->index != SND_SOC_TPLG_INDEX_ALL) 1670 return 0; 1671 1672 tplg->index = hdr->index; 1673 1674 switch (hdr->type) { 1675 case SND_SOC_TPLG_TYPE_MIXER: 1676 case SND_SOC_TPLG_TYPE_ENUM: 1677 case SND_SOC_TPLG_TYPE_BYTES: 1678 return soc_tplg_kcontrol_elems_load(tplg, hdr); 1679 case SND_SOC_TPLG_TYPE_DAPM_GRAPH: 1680 return soc_tplg_dapm_graph_elems_load(tplg, hdr); 1681 case SND_SOC_TPLG_TYPE_DAPM_WIDGET: 1682 return soc_tplg_dapm_widget_elems_load(tplg, hdr); 1683 case SND_SOC_TPLG_TYPE_PCM: 1684 case SND_SOC_TPLG_TYPE_DAI_LINK: 1685 case SND_SOC_TPLG_TYPE_CODEC_LINK: 1686 return soc_tplg_pcm_dai_elems_load(tplg, hdr); 1687 case SND_SOC_TPLG_TYPE_MANIFEST: 1688 return soc_tplg_manifest_load(tplg, hdr); 1689 default: 1690 /* bespoke vendor data object */ 1691 return soc_tplg_vendor_load(tplg, hdr); 1692 } 1693 1694 return 0; 1695 } 1696 1697 /* process the topology file headers */ 1698 static int soc_tplg_process_headers(struct soc_tplg *tplg) 1699 { 1700 struct snd_soc_tplg_hdr *hdr; 1701 int ret; 1702 1703 tplg->pass = SOC_TPLG_PASS_START; 1704 1705 /* process the header types from start to end */ 1706 while (tplg->pass <= SOC_TPLG_PASS_END) { 1707 1708 tplg->hdr_pos = tplg->fw->data; 1709 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; 1710 1711 while (!soc_tplg_is_eof(tplg)) { 1712 1713 /* make sure header is valid before loading */ 1714 ret = soc_valid_header(tplg, hdr); 1715 if (ret < 0) 1716 return ret; 1717 else if (ret == 0) 1718 break; 1719 1720 /* load the header object */ 1721 ret = soc_tplg_load_header(tplg, hdr); 1722 if (ret < 0) 1723 return ret; 1724 1725 /* goto next header */ 1726 tplg->hdr_pos += hdr->payload_size + 1727 sizeof(struct snd_soc_tplg_hdr); 1728 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; 1729 } 1730 1731 /* next data type pass */ 1732 tplg->pass++; 1733 } 1734 1735 /* signal DAPM we are complete */ 1736 ret = soc_tplg_dapm_complete(tplg); 1737 if (ret < 0) 1738 dev_err(tplg->dev, 1739 "ASoC: failed to initialise DAPM from Firmware\n"); 1740 1741 return ret; 1742 } 1743 1744 static int soc_tplg_load(struct soc_tplg *tplg) 1745 { 1746 int ret; 1747 1748 ret = soc_tplg_process_headers(tplg); 1749 if (ret == 0) 1750 soc_tplg_complete(tplg); 1751 1752 return ret; 1753 } 1754 1755 /* load audio component topology from "firmware" file */ 1756 int snd_soc_tplg_component_load(struct snd_soc_component *comp, 1757 struct snd_soc_tplg_ops *ops, const struct firmware *fw, u32 id) 1758 { 1759 struct soc_tplg tplg; 1760 1761 /* setup parsing context */ 1762 memset(&tplg, 0, sizeof(tplg)); 1763 tplg.fw = fw; 1764 tplg.dev = comp->dev; 1765 tplg.comp = comp; 1766 tplg.ops = ops; 1767 tplg.req_index = id; 1768 tplg.io_ops = ops->io_ops; 1769 tplg.io_ops_count = ops->io_ops_count; 1770 tplg.bytes_ext_ops = ops->bytes_ext_ops; 1771 tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count; 1772 1773 return soc_tplg_load(&tplg); 1774 } 1775 EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load); 1776 1777 /* remove this dynamic widget */ 1778 void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget *w) 1779 { 1780 /* make sure we are a widget */ 1781 if (w->dobj.type != SND_SOC_DOBJ_WIDGET) 1782 return; 1783 1784 remove_widget(w->dapm->component, &w->dobj, SOC_TPLG_PASS_WIDGET); 1785 } 1786 EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove); 1787 1788 /* remove all dynamic widgets from this DAPM context */ 1789 void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm, 1790 u32 index) 1791 { 1792 struct snd_soc_dapm_widget *w, *next_w; 1793 1794 list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { 1795 1796 /* make sure we are a widget with correct context */ 1797 if (w->dobj.type != SND_SOC_DOBJ_WIDGET || w->dapm != dapm) 1798 continue; 1799 1800 /* match ID */ 1801 if (w->dobj.index != index && 1802 w->dobj.index != SND_SOC_TPLG_INDEX_ALL) 1803 continue; 1804 /* check and free and dynamic widget kcontrols */ 1805 snd_soc_tplg_widget_remove(w); 1806 snd_soc_dapm_free_widget(w); 1807 } 1808 snd_soc_dapm_reset_cache(dapm); 1809 } 1810 EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all); 1811 1812 /* remove dynamic controls from the component driver */ 1813 int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index) 1814 { 1815 struct snd_soc_dobj *dobj, *next_dobj; 1816 int pass = SOC_TPLG_PASS_END; 1817 1818 /* process the header types from end to start */ 1819 while (pass >= SOC_TPLG_PASS_START) { 1820 1821 /* remove mixer controls */ 1822 list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list, 1823 list) { 1824 1825 /* match index */ 1826 if (dobj->index != index && 1827 dobj->index != SND_SOC_TPLG_INDEX_ALL) 1828 continue; 1829 1830 switch (dobj->type) { 1831 case SND_SOC_DOBJ_MIXER: 1832 remove_mixer(comp, dobj, pass); 1833 break; 1834 case SND_SOC_DOBJ_ENUM: 1835 remove_enum(comp, dobj, pass); 1836 break; 1837 case SND_SOC_DOBJ_BYTES: 1838 remove_bytes(comp, dobj, pass); 1839 break; 1840 case SND_SOC_DOBJ_WIDGET: 1841 remove_widget(comp, dobj, pass); 1842 break; 1843 case SND_SOC_DOBJ_PCM: 1844 case SND_SOC_DOBJ_DAI_LINK: 1845 case SND_SOC_DOBJ_CODEC_LINK: 1846 remove_pcm_dai(comp, dobj, pass); 1847 break; 1848 default: 1849 dev_err(comp->dev, "ASoC: invalid component type %d for removal\n", 1850 dobj->type); 1851 break; 1852 } 1853 } 1854 pass--; 1855 } 1856 1857 /* let caller know if FW can be freed when no objects are left */ 1858 return !list_empty(&comp->dobj_list); 1859 } 1860 EXPORT_SYMBOL_GPL(snd_soc_tplg_component_remove); 1861