2238 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// soc-topology.c -- ALSA SoC Topology4//5// Copyright (C) 2012 Texas Instruments Inc.6// Copyright (C) 2015 Intel Corporation.7//8// Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>9// K, Mythri P <mythri.p.k@intel.com>10// Prusty, Subhransu S <subhransu.s.prusty@intel.com>11// B, Jayachandran <jayachandran.b@intel.com>12// Abdullah, Omair M <omair.m.abdullah@intel.com>13// Jin, Yao <yao.jin@intel.com>14// Lin, Mengdong <mengdong.lin@intel.com>15//16// Add support to read audio firmware topology alongside firmware text. The17// topology data can contain kcontrols, DAPM graphs, widgets, DAIs, DAI links,18// equalizers, firmware, coefficients etc.19//20// This file only manages the core ALSA and ASoC components, all other bespoke21// firmware topology data is passed to component drivers for bespoke handling.22 23#include <linux/kernel.h>24#include <linux/export.h>25#include <linux/list.h>26#include <linux/firmware.h>27#include <linux/slab.h>28#include <sound/soc.h>29#include <sound/soc-dapm.h>30#include <sound/soc-topology.h>31#include <sound/tlv.h>32 33#define SOC_TPLG_MAGIC_BIG_ENDIAN 0x436F5341 /* ASoC in reverse */34 35/*36 * We make several passes over the data (since it wont necessarily be ordered)37 * and process objects in the following order. This guarantees the component38 * drivers will be ready with any vendor data before the mixers and DAPM objects39 * are loaded (that may make use of the vendor data).40 */41#define SOC_TPLG_PASS_MANIFEST 042#define SOC_TPLG_PASS_VENDOR 143#define SOC_TPLG_PASS_CONTROL 244#define SOC_TPLG_PASS_WIDGET 345#define SOC_TPLG_PASS_PCM_DAI 446#define SOC_TPLG_PASS_GRAPH 547#define SOC_TPLG_PASS_BE_DAI 648#define SOC_TPLG_PASS_LINK 749 50#define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST51#define SOC_TPLG_PASS_END SOC_TPLG_PASS_LINK52 53/* topology context */54struct soc_tplg {55 const struct firmware *fw;56 57 /* runtime FW parsing */58 const u8 *pos; /* read position */59 const u8 *hdr_pos; /* header position */60 unsigned int pass; /* pass number */61 62 /* component caller */63 struct device *dev;64 struct snd_soc_component *comp;65 u32 index; /* current block index */66 67 /* vendor specific kcontrol operations */68 const struct snd_soc_tplg_kcontrol_ops *io_ops;69 int io_ops_count;70 71 /* vendor specific bytes ext handlers, for TLV bytes controls */72 const struct snd_soc_tplg_bytes_ext_ops *bytes_ext_ops;73 int bytes_ext_ops_count;74 75 /* optional fw loading callbacks to component drivers */76 const struct snd_soc_tplg_ops *ops;77};78 79/* check we dont overflow the data for this control chunk */80static int soc_tplg_check_elem_count(struct soc_tplg *tplg, size_t elem_size,81 unsigned int count, size_t bytes, const char *elem_type)82{83 const u8 *end = tplg->pos + elem_size * count;84 85 if (end > tplg->fw->data + tplg->fw->size) {86 dev_err(tplg->dev, "ASoC: %s overflow end of data\n",87 elem_type);88 return -EINVAL;89 }90 91 /* check there is enough room in chunk for control.92 extra bytes at the end of control are for vendor data here */93 if (elem_size * count > bytes) {94 dev_err(tplg->dev,95 "ASoC: %s count %d of size %zu is bigger than chunk %zu\n",96 elem_type, count, elem_size, bytes);97 return -EINVAL;98 }99 100 return 0;101}102 103static inline bool soc_tplg_is_eof(struct soc_tplg *tplg)104{105 const u8 *end = tplg->hdr_pos;106 107 if (end >= tplg->fw->data + tplg->fw->size)108 return true;109 return false;110}111 112static inline unsigned long soc_tplg_get_hdr_offset(struct soc_tplg *tplg)113{114 return (unsigned long)(tplg->hdr_pos - tplg->fw->data);115}116 117static inline unsigned long soc_tplg_get_offset(struct soc_tplg *tplg)118{119 return (unsigned long)(tplg->pos - tplg->fw->data);120}121 122/* mapping of Kcontrol types and associated operations. */123static const struct snd_soc_tplg_kcontrol_ops io_ops[] = {124 {SND_SOC_TPLG_CTL_VOLSW, snd_soc_get_volsw,125 snd_soc_put_volsw, snd_soc_info_volsw},126 {SND_SOC_TPLG_CTL_VOLSW_SX, snd_soc_get_volsw_sx,127 snd_soc_put_volsw_sx, NULL},128 {SND_SOC_TPLG_CTL_ENUM, snd_soc_get_enum_double,129 snd_soc_put_enum_double, snd_soc_info_enum_double},130 {SND_SOC_TPLG_CTL_ENUM_VALUE, snd_soc_get_enum_double,131 snd_soc_put_enum_double, NULL},132 {SND_SOC_TPLG_CTL_BYTES, snd_soc_bytes_get,133 snd_soc_bytes_put, snd_soc_bytes_info},134 {SND_SOC_TPLG_CTL_RANGE, snd_soc_get_volsw_range,135 snd_soc_put_volsw_range, snd_soc_info_volsw_range},136 {SND_SOC_TPLG_CTL_VOLSW_XR_SX, snd_soc_get_xr_sx,137 snd_soc_put_xr_sx, snd_soc_info_xr_sx},138 {SND_SOC_TPLG_CTL_STROBE, snd_soc_get_strobe,139 snd_soc_put_strobe, NULL},140 {SND_SOC_TPLG_DAPM_CTL_VOLSW, snd_soc_dapm_get_volsw,141 snd_soc_dapm_put_volsw, snd_soc_info_volsw},142 {SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE, snd_soc_dapm_get_enum_double,143 snd_soc_dapm_put_enum_double, snd_soc_info_enum_double},144 {SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT, snd_soc_dapm_get_enum_double,145 snd_soc_dapm_put_enum_double, NULL},146 {SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE, snd_soc_dapm_get_enum_double,147 snd_soc_dapm_put_enum_double, NULL},148 {SND_SOC_TPLG_DAPM_CTL_PIN, snd_soc_dapm_get_pin_switch,149 snd_soc_dapm_put_pin_switch, snd_soc_dapm_info_pin_switch},150};151 152struct soc_tplg_map {153 int uid;154 int kid;155};156 157/* mapping of widget types from UAPI IDs to kernel IDs */158static const struct soc_tplg_map dapm_map[] = {159 {SND_SOC_TPLG_DAPM_INPUT, snd_soc_dapm_input},160 {SND_SOC_TPLG_DAPM_OUTPUT, snd_soc_dapm_output},161 {SND_SOC_TPLG_DAPM_MUX, snd_soc_dapm_mux},162 {SND_SOC_TPLG_DAPM_MIXER, snd_soc_dapm_mixer},163 {SND_SOC_TPLG_DAPM_PGA, snd_soc_dapm_pga},164 {SND_SOC_TPLG_DAPM_OUT_DRV, snd_soc_dapm_out_drv},165 {SND_SOC_TPLG_DAPM_ADC, snd_soc_dapm_adc},166 {SND_SOC_TPLG_DAPM_DAC, snd_soc_dapm_dac},167 {SND_SOC_TPLG_DAPM_SWITCH, snd_soc_dapm_switch},168 {SND_SOC_TPLG_DAPM_PRE, snd_soc_dapm_pre},169 {SND_SOC_TPLG_DAPM_POST, snd_soc_dapm_post},170 {SND_SOC_TPLG_DAPM_AIF_IN, snd_soc_dapm_aif_in},171 {SND_SOC_TPLG_DAPM_AIF_OUT, snd_soc_dapm_aif_out},172 {SND_SOC_TPLG_DAPM_DAI_IN, snd_soc_dapm_dai_in},173 {SND_SOC_TPLG_DAPM_DAI_OUT, snd_soc_dapm_dai_out},174 {SND_SOC_TPLG_DAPM_DAI_LINK, snd_soc_dapm_dai_link},175 {SND_SOC_TPLG_DAPM_BUFFER, snd_soc_dapm_buffer},176 {SND_SOC_TPLG_DAPM_SCHEDULER, snd_soc_dapm_scheduler},177 {SND_SOC_TPLG_DAPM_EFFECT, snd_soc_dapm_effect},178 {SND_SOC_TPLG_DAPM_SIGGEN, snd_soc_dapm_siggen},179 {SND_SOC_TPLG_DAPM_SRC, snd_soc_dapm_src},180 {SND_SOC_TPLG_DAPM_ASRC, snd_soc_dapm_asrc},181 {SND_SOC_TPLG_DAPM_ENCODER, snd_soc_dapm_encoder},182 {SND_SOC_TPLG_DAPM_DECODER, snd_soc_dapm_decoder},183};184 185static int tplg_chan_get_reg(struct soc_tplg *tplg,186 struct snd_soc_tplg_channel *chan, int map)187{188 int i;189 190 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) {191 if (le32_to_cpu(chan[i].id) == map)192 return le32_to_cpu(chan[i].reg);193 }194 195 return -EINVAL;196}197 198static int tplg_chan_get_shift(struct soc_tplg *tplg,199 struct snd_soc_tplg_channel *chan, int map)200{201 int i;202 203 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) {204 if (le32_to_cpu(chan[i].id) == map)205 return le32_to_cpu(chan[i].shift);206 }207 208 return -EINVAL;209}210 211static int get_widget_id(int tplg_type)212{213 int i;214 215 for (i = 0; i < ARRAY_SIZE(dapm_map); i++) {216 if (tplg_type == dapm_map[i].uid)217 return dapm_map[i].kid;218 }219 220 return -EINVAL;221}222 223static inline void soc_bind_err(struct soc_tplg *tplg,224 struct snd_soc_tplg_ctl_hdr *hdr, int index)225{226 dev_err(tplg->dev,227 "ASoC: invalid control type (g,p,i) %d:%d:%d index %d at 0x%lx\n",228 hdr->ops.get, hdr->ops.put, hdr->ops.info, index,229 soc_tplg_get_offset(tplg));230}231 232static inline void soc_control_err(struct soc_tplg *tplg,233 struct snd_soc_tplg_ctl_hdr *hdr, const char *name)234{235 dev_err(tplg->dev,236 "ASoC: no complete control IO handler for %s type (g,p,i) %d:%d:%d at 0x%lx\n",237 name, hdr->ops.get, hdr->ops.put, hdr->ops.info,238 soc_tplg_get_offset(tplg));239}240 241/* pass vendor data to component driver for processing */242static int soc_tplg_vendor_load(struct soc_tplg *tplg,243 struct snd_soc_tplg_hdr *hdr)244{245 int ret = 0;246 247 if (tplg->ops && tplg->ops->vendor_load)248 ret = tplg->ops->vendor_load(tplg->comp, tplg->index, hdr);249 else {250 dev_err(tplg->dev, "ASoC: no vendor load callback for ID %d\n",251 hdr->vendor_type);252 return -EINVAL;253 }254 255 if (ret < 0)256 dev_err(tplg->dev,257 "ASoC: vendor load failed at hdr offset %ld/0x%lx for type %d:%d\n",258 soc_tplg_get_hdr_offset(tplg),259 soc_tplg_get_hdr_offset(tplg),260 hdr->type, hdr->vendor_type);261 return ret;262}263 264/* optionally pass new dynamic widget to component driver. This is mainly for265 * external widgets where we can assign private data/ops */266static int soc_tplg_widget_load(struct soc_tplg *tplg,267 struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w)268{269 if (tplg->ops && tplg->ops->widget_load)270 return tplg->ops->widget_load(tplg->comp, tplg->index, w,271 tplg_w);272 273 return 0;274}275 276/* optionally pass new dynamic widget to component driver. This is mainly for277 * external widgets where we can assign private data/ops */278static int soc_tplg_widget_ready(struct soc_tplg *tplg,279 struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w)280{281 if (tplg->ops && tplg->ops->widget_ready)282 return tplg->ops->widget_ready(tplg->comp, tplg->index, w,283 tplg_w);284 285 return 0;286}287 288/* pass DAI configurations to component driver for extra initialization */289static int soc_tplg_dai_load(struct soc_tplg *tplg,290 struct snd_soc_dai_driver *dai_drv,291 struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai)292{293 if (tplg->ops && tplg->ops->dai_load)294 return tplg->ops->dai_load(tplg->comp, tplg->index, dai_drv,295 pcm, dai);296 297 return 0;298}299 300/* pass link configurations to component driver for extra initialization */301static int soc_tplg_dai_link_load(struct soc_tplg *tplg,302 struct snd_soc_dai_link *link, struct snd_soc_tplg_link_config *cfg)303{304 if (tplg->ops && tplg->ops->link_load)305 return tplg->ops->link_load(tplg->comp, tplg->index, link, cfg);306 307 return 0;308}309 310/* tell the component driver that all firmware has been loaded in this request */311static int soc_tplg_complete(struct soc_tplg *tplg)312{313 if (tplg->ops && tplg->ops->complete)314 return tplg->ops->complete(tplg->comp);315 316 return 0;317}318 319/* add a dynamic kcontrol */320static int soc_tplg_add_dcontrol(struct snd_card *card, struct device *dev,321 const struct snd_kcontrol_new *control_new, const char *prefix,322 void *data, struct snd_kcontrol **kcontrol)323{324 int err;325 326 *kcontrol = snd_soc_cnew(control_new, data, control_new->name, prefix);327 if (*kcontrol == NULL) {328 dev_err(dev, "ASoC: Failed to create new kcontrol %s\n",329 control_new->name);330 return -ENOMEM;331 }332 333 err = snd_ctl_add(card, *kcontrol);334 if (err < 0) {335 dev_err(dev, "ASoC: Failed to add %s: %d\n",336 control_new->name, err);337 return err;338 }339 340 return 0;341}342 343/* add a dynamic kcontrol for component driver */344static int soc_tplg_add_kcontrol(struct soc_tplg *tplg,345 struct snd_kcontrol_new *k, struct snd_kcontrol **kcontrol)346{347 struct snd_soc_component *comp = tplg->comp;348 349 return soc_tplg_add_dcontrol(comp->card->snd_card,350 tplg->dev, k, comp->name_prefix, comp, kcontrol);351}352 353/* remove kcontrol */354static void soc_tplg_remove_kcontrol(struct snd_soc_component *comp, struct snd_soc_dobj *dobj,355 int pass)356{357 struct snd_card *card = comp->card->snd_card;358 359 if (pass != SOC_TPLG_PASS_CONTROL)360 return;361 362 if (dobj->unload)363 dobj->unload(comp, dobj);364 365 snd_ctl_remove(card, dobj->control.kcontrol);366 list_del(&dobj->list);367}368 369/* remove a route */370static void soc_tplg_remove_route(struct snd_soc_component *comp,371 struct snd_soc_dobj *dobj, int pass)372{373 if (pass != SOC_TPLG_PASS_GRAPH)374 return;375 376 if (dobj->unload)377 dobj->unload(comp, dobj);378 379 list_del(&dobj->list);380}381 382/* remove a widget and it's kcontrols - routes must be removed first */383static void soc_tplg_remove_widget(struct snd_soc_component *comp,384 struct snd_soc_dobj *dobj, int pass)385{386 struct snd_card *card = comp->card->snd_card;387 struct snd_soc_dapm_widget *w =388 container_of(dobj, struct snd_soc_dapm_widget, dobj);389 int i;390 391 if (pass != SOC_TPLG_PASS_WIDGET)392 return;393 394 if (dobj->unload)395 dobj->unload(comp, dobj);396 397 if (w->kcontrols)398 for (i = 0; i < w->num_kcontrols; i++)399 snd_ctl_remove(card, w->kcontrols[i]);400 401 list_del(&dobj->list);402 403 /* widget w is freed by soc-dapm.c */404}405 406/* remove DAI configurations */407static void soc_tplg_remove_dai(struct snd_soc_component *comp,408 struct snd_soc_dobj *dobj, int pass)409{410 struct snd_soc_dai_driver *dai_drv =411 container_of(dobj, struct snd_soc_dai_driver, dobj);412 struct snd_soc_dai *dai, *_dai;413 414 if (pass != SOC_TPLG_PASS_PCM_DAI)415 return;416 417 if (dobj->unload)418 dobj->unload(comp, dobj);419 420 for_each_component_dais_safe(comp, dai, _dai)421 if (dai->driver == dai_drv)422 snd_soc_unregister_dai(dai);423 424 list_del(&dobj->list);425}426 427/* remove link configurations */428static void soc_tplg_remove_link(struct snd_soc_component *comp,429 struct snd_soc_dobj *dobj, int pass)430{431 struct snd_soc_dai_link *link =432 container_of(dobj, struct snd_soc_dai_link, dobj);433 434 if (pass != SOC_TPLG_PASS_PCM_DAI)435 return;436 437 if (dobj->unload)438 dobj->unload(comp, dobj);439 440 list_del(&dobj->list);441 snd_soc_remove_pcm_runtime(comp->card,442 snd_soc_get_pcm_runtime(comp->card, link));443}444 445/* unload dai link */446static void remove_backend_link(struct snd_soc_component *comp,447 struct snd_soc_dobj *dobj, int pass)448{449 if (pass != SOC_TPLG_PASS_LINK)450 return;451 452 if (dobj->unload)453 dobj->unload(comp, dobj);454 455 /*456 * We don't free the link here as what soc_tplg_remove_link() do since BE457 * links are not allocated by topology.458 * We however need to reset the dobj type to its initial values459 */460 dobj->type = SND_SOC_DOBJ_NONE;461 list_del(&dobj->list);462}463 464/* bind a kcontrol to it's IO handlers */465static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr,466 struct snd_kcontrol_new *k,467 const struct soc_tplg *tplg)468{469 const struct snd_soc_tplg_kcontrol_ops *ops;470 const struct snd_soc_tplg_bytes_ext_ops *ext_ops;471 int num_ops, i;472 473 if (le32_to_cpu(hdr->ops.info) == SND_SOC_TPLG_CTL_BYTES474 && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER475 && (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ476 || k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)477 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {478 struct soc_bytes_ext *sbe;479 struct snd_soc_tplg_bytes_control *be;480 481 sbe = (struct soc_bytes_ext *)k->private_value;482 be = container_of(hdr, struct snd_soc_tplg_bytes_control, hdr);483 484 /* TLV bytes controls need standard kcontrol info handler,485 * TLV callback and extended put/get handlers.486 */487 k->info = snd_soc_bytes_info_ext;488 k->tlv.c = snd_soc_bytes_tlv_callback;489 490 /*491 * When a topology-based implementation abuses the492 * control interface and uses bytes_ext controls of493 * more than 512 bytes, we need to disable the size494 * checks, otherwise accesses to such controls will495 * return an -EINVAL error and prevent the card from496 * being configured.497 */498 if (sbe->max > 512)499 k->access |= SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK;500 501 ext_ops = tplg->bytes_ext_ops;502 num_ops = tplg->bytes_ext_ops_count;503 for (i = 0; i < num_ops; i++) {504 if (!sbe->put &&505 ext_ops[i].id == le32_to_cpu(be->ext_ops.put))506 sbe->put = ext_ops[i].put;507 if (!sbe->get &&508 ext_ops[i].id == le32_to_cpu(be->ext_ops.get))509 sbe->get = ext_ops[i].get;510 }511 512 if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) && !sbe->get)513 return -EINVAL;514 if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) && !sbe->put)515 return -EINVAL;516 return 0;517 }518 519 /* try and map vendor specific kcontrol handlers first */520 ops = tplg->io_ops;521 num_ops = tplg->io_ops_count;522 for (i = 0; i < num_ops; i++) {523 524 if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put))525 k->put = ops[i].put;526 if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get))527 k->get = ops[i].get;528 if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info))529 k->info = ops[i].info;530 }531 532 /* vendor specific handlers found ? */533 if (k->put && k->get && k->info)534 return 0;535 536 /* none found so try standard kcontrol handlers */537 ops = io_ops;538 num_ops = ARRAY_SIZE(io_ops);539 for (i = 0; i < num_ops; i++) {540 541 if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put))542 k->put = ops[i].put;543 if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get))544 k->get = ops[i].get;545 if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info))546 k->info = ops[i].info;547 }548 549 /* standard handlers found ? */550 if (k->put && k->get && k->info)551 return 0;552 553 /* nothing to bind */554 return -EINVAL;555}556 557/* bind a widgets to it's evnt handlers */558int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w,559 const struct snd_soc_tplg_widget_events *events,560 int num_events, u16 event_type)561{562 int i;563 564 w->event = NULL;565 566 for (i = 0; i < num_events; i++) {567 if (event_type == events[i].type) {568 569 /* found - so assign event */570 w->event = events[i].event_handler;571 return 0;572 }573 }574 575 /* not found */576 return -EINVAL;577}578EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_bind_event);579 580/* optionally pass new dynamic kcontrol to component driver. */581static int soc_tplg_control_load(struct soc_tplg *tplg,582 struct snd_kcontrol_new *k, struct snd_soc_tplg_ctl_hdr *hdr)583{584 int ret = 0;585 586 if (tplg->ops && tplg->ops->control_load)587 ret = tplg->ops->control_load(tplg->comp, tplg->index, k, hdr);588 589 if (ret)590 dev_err(tplg->dev, "ASoC: failed to init %s\n", hdr->name);591 592 return ret;593}594 595 596static int soc_tplg_create_tlv_db_scale(struct soc_tplg *tplg,597 struct snd_kcontrol_new *kc, struct snd_soc_tplg_tlv_dbscale *scale)598{599 unsigned int item_len = 2 * sizeof(unsigned int);600 unsigned int *p;601 602 p = devm_kzalloc(tplg->dev, item_len + 2 * sizeof(unsigned int), GFP_KERNEL);603 if (!p)604 return -ENOMEM;605 606 p[0] = SNDRV_CTL_TLVT_DB_SCALE;607 p[1] = item_len;608 p[2] = le32_to_cpu(scale->min);609 p[3] = (le32_to_cpu(scale->step) & TLV_DB_SCALE_MASK)610 | (le32_to_cpu(scale->mute) ? TLV_DB_SCALE_MUTE : 0);611 612 kc->tlv.p = (void *)p;613 return 0;614}615 616static int soc_tplg_create_tlv(struct soc_tplg *tplg,617 struct snd_kcontrol_new *kc, struct snd_soc_tplg_ctl_hdr *tc)618{619 struct snd_soc_tplg_ctl_tlv *tplg_tlv;620 u32 access = le32_to_cpu(tc->access);621 622 if (!(access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE))623 return 0;624 625 if (!(access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {626 tplg_tlv = &tc->tlv;627 switch (le32_to_cpu(tplg_tlv->type)) {628 case SNDRV_CTL_TLVT_DB_SCALE:629 return soc_tplg_create_tlv_db_scale(tplg, kc,630 &tplg_tlv->scale);631 632 /* TODO: add support for other TLV types */633 default:634 dev_dbg(tplg->dev, "Unsupported TLV type %d\n",635 tplg_tlv->type);636 return -EINVAL;637 }638 }639 640 return 0;641}642 643static int soc_tplg_control_dmixer_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc)644{645 struct snd_soc_tplg_mixer_control *mc;646 struct soc_mixer_control *sm;647 int err;648 649 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos;650 651 /* validate kcontrol */652 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN)653 return -EINVAL;654 655 sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL);656 if (!sm)657 return -ENOMEM;658 659 tplg->pos += sizeof(struct snd_soc_tplg_mixer_control) + le32_to_cpu(mc->priv.size);660 661 dev_dbg(tplg->dev, "ASoC: adding mixer kcontrol %s with access 0x%x\n",662 mc->hdr.name, mc->hdr.access);663 664 kc->name = devm_kstrdup(tplg->dev, mc->hdr.name, GFP_KERNEL);665 if (!kc->name)666 return -ENOMEM;667 kc->private_value = (long)sm;668 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER;669 kc->access = le32_to_cpu(mc->hdr.access);670 671 /* we only support FL/FR channel mapping atm */672 sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL);673 sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR);674 sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL);675 sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR);676 677 sm->max = le32_to_cpu(mc->max);678 sm->min = le32_to_cpu(mc->min);679 sm->invert = le32_to_cpu(mc->invert);680 sm->platform_max = le32_to_cpu(mc->platform_max);681 682 /* map io handlers */683 err = soc_tplg_kcontrol_bind_io(&mc->hdr, kc, tplg);684 if (err) {685 soc_control_err(tplg, &mc->hdr, mc->hdr.name);686 return err;687 }688 689 /* create any TLV data */690 err = soc_tplg_create_tlv(tplg, kc, &mc->hdr);691 if (err < 0) {692 dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name);693 return err;694 }695 696 /* pass control to driver for optional further init */697 return soc_tplg_control_load(tplg, kc, &mc->hdr);698}699 700static int soc_tplg_denum_create_texts(struct soc_tplg *tplg, struct soc_enum *se,701 struct snd_soc_tplg_enum_control *ec)702{703 int i, ret;704 705 if (le32_to_cpu(ec->items) > ARRAY_SIZE(ec->texts))706 return -EINVAL;707 708 se->dobj.control.dtexts =709 devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), sizeof(char *), GFP_KERNEL);710 if (se->dobj.control.dtexts == NULL)711 return -ENOMEM;712 713 for (i = 0; i < le32_to_cpu(ec->items); i++) {714 715 if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==716 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {717 ret = -EINVAL;718 goto err;719 }720 721 se->dobj.control.dtexts[i] = devm_kstrdup(tplg->dev, ec->texts[i], GFP_KERNEL);722 if (!se->dobj.control.dtexts[i]) {723 ret = -ENOMEM;724 goto err;725 }726 }727 728 se->items = le32_to_cpu(ec->items);729 se->texts = (const char * const *)se->dobj.control.dtexts;730 return 0;731 732err:733 return ret;734}735 736static int soc_tplg_denum_create_values(struct soc_tplg *tplg, struct soc_enum *se,737 struct snd_soc_tplg_enum_control *ec)738{739 int i;740 741 /*742 * Following "if" checks if we have at most SND_SOC_TPLG_NUM_TEXTS743 * values instead of using ARRAY_SIZE(ec->values) due to the fact that744 * it is oversized for its purpose. Additionally it is done so because745 * it is defined in UAPI header where it can't be easily changed.746 */747 if (le32_to_cpu(ec->items) > SND_SOC_TPLG_NUM_TEXTS)748 return -EINVAL;749 750 se->dobj.control.dvalues = devm_kcalloc(tplg->dev, le32_to_cpu(ec->items),751 sizeof(*se->dobj.control.dvalues),752 GFP_KERNEL);753 if (!se->dobj.control.dvalues)754 return -ENOMEM;755 756 /* convert from little-endian */757 for (i = 0; i < le32_to_cpu(ec->items); i++) {758 se->dobj.control.dvalues[i] = le32_to_cpu(ec->values[i]);759 }760 761 se->items = le32_to_cpu(ec->items);762 se->values = (const unsigned int *)se->dobj.control.dvalues;763 return 0;764}765 766static int soc_tplg_control_denum_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc)767{768 struct snd_soc_tplg_enum_control *ec;769 struct soc_enum *se;770 int err;771 772 ec = (struct snd_soc_tplg_enum_control *)tplg->pos;773 774 /* validate kcontrol */775 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN)776 return -EINVAL;777 778 se = devm_kzalloc(tplg->dev, sizeof(*se), GFP_KERNEL);779 if (!se)780 return -ENOMEM;781 782 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + le32_to_cpu(ec->priv.size));783 784 dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", ec->hdr.name, ec->items);785 786 kc->name = devm_kstrdup(tplg->dev, ec->hdr.name, GFP_KERNEL);787 if (!kc->name)788 return -ENOMEM;789 kc->private_value = (long)se;790 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER;791 kc->access = le32_to_cpu(ec->hdr.access);792 793 /* we only support FL/FR channel mapping atm */794 se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);795 se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL);796 se->shift_r = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR);797 798 se->mask = le32_to_cpu(ec->mask);799 800 switch (le32_to_cpu(ec->hdr.ops.info)) {801 case SND_SOC_TPLG_CTL_ENUM_VALUE:802 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:803 err = soc_tplg_denum_create_values(tplg, se, ec);804 if (err < 0) {805 dev_err(tplg->dev, "ASoC: could not create values for %s\n", ec->hdr.name);806 return err;807 }808 fallthrough;809 case SND_SOC_TPLG_CTL_ENUM:810 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:811 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:812 err = soc_tplg_denum_create_texts(tplg, se, ec);813 if (err < 0) {814 dev_err(tplg->dev, "ASoC: could not create texts for %s\n", ec->hdr.name);815 return err;816 }817 break;818 default:819 dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n",820 ec->hdr.ops.info, ec->hdr.name);821 return -EINVAL;822 }823 824 /* map io handlers */825 err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg);826 if (err) {827 soc_control_err(tplg, &ec->hdr, ec->hdr.name);828 return err;829 }830 831 /* pass control to driver for optional further init */832 return soc_tplg_control_load(tplg, kc, &ec->hdr);833}834 835static int soc_tplg_control_dbytes_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc)836{837 struct snd_soc_tplg_bytes_control *be;838 struct soc_bytes_ext *sbe;839 int err;840 841 be = (struct snd_soc_tplg_bytes_control *)tplg->pos;842 843 /* validate kcontrol */844 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN)845 return -EINVAL;846 847 sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL);848 if (!sbe)849 return -ENOMEM;850 851 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + le32_to_cpu(be->priv.size));852 853 dev_dbg(tplg->dev, "ASoC: adding bytes kcontrol %s with access 0x%x\n",854 be->hdr.name, be->hdr.access);855 856 kc->name = devm_kstrdup(tplg->dev, be->hdr.name, GFP_KERNEL);857 if (!kc->name)858 return -ENOMEM;859 kc->private_value = (long)sbe;860 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER;861 kc->access = le32_to_cpu(be->hdr.access);862 863 sbe->max = le32_to_cpu(be->max);864 865 /* map standard io handlers and check for external handlers */866 err = soc_tplg_kcontrol_bind_io(&be->hdr, kc, tplg);867 if (err) {868 soc_control_err(tplg, &be->hdr, be->hdr.name);869 return err;870 }871 872 /* pass control to driver for optional further init */873 return soc_tplg_control_load(tplg, kc, &be->hdr);874}875 876static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size)877{878 struct snd_kcontrol_new kc = {0};879 struct soc_bytes_ext *sbe;880 int ret;881 882 if (soc_tplg_check_elem_count(tplg,883 sizeof(struct snd_soc_tplg_bytes_control),884 1, size, "mixer bytes"))885 return -EINVAL;886 887 ret = soc_tplg_control_dbytes_create(tplg, &kc);888 if (ret)889 return ret;890 891 /* register dynamic object */892 sbe = (struct soc_bytes_ext *)kc.private_value;893 894 INIT_LIST_HEAD(&sbe->dobj.list);895 sbe->dobj.type = SND_SOC_DOBJ_BYTES;896 sbe->dobj.index = tplg->index;897 if (tplg->ops)898 sbe->dobj.unload = tplg->ops->control_unload;899 900 /* create control directly */901 ret = soc_tplg_add_kcontrol(tplg, &kc, &sbe->dobj.control.kcontrol);902 if (ret < 0)903 return ret;904 905 list_add(&sbe->dobj.list, &tplg->comp->dobj_list);906 907 return ret;908}909 910static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size)911{912 struct snd_kcontrol_new kc = {0};913 struct soc_mixer_control *sm;914 int ret;915 916 if (soc_tplg_check_elem_count(tplg,917 sizeof(struct snd_soc_tplg_mixer_control),918 1, size, "mixers"))919 return -EINVAL;920 921 ret = soc_tplg_control_dmixer_create(tplg, &kc);922 if (ret)923 return ret;924 925 /* register dynamic object */926 sm = (struct soc_mixer_control *)kc.private_value;927 928 INIT_LIST_HEAD(&sm->dobj.list);929 sm->dobj.type = SND_SOC_DOBJ_MIXER;930 sm->dobj.index = tplg->index;931 if (tplg->ops)932 sm->dobj.unload = tplg->ops->control_unload;933 934 /* create control directly */935 ret = soc_tplg_add_kcontrol(tplg, &kc, &sm->dobj.control.kcontrol);936 if (ret < 0)937 return ret;938 939 list_add(&sm->dobj.list, &tplg->comp->dobj_list);940 941 return ret;942}943 944static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size)945{946 struct snd_kcontrol_new kc = {0};947 struct soc_enum *se;948 int ret;949 950 if (soc_tplg_check_elem_count(tplg,951 sizeof(struct snd_soc_tplg_enum_control),952 1, size, "enums"))953 return -EINVAL;954 955 ret = soc_tplg_control_denum_create(tplg, &kc);956 if (ret)957 return ret;958 959 /* register dynamic object */960 se = (struct soc_enum *)kc.private_value;961 962 INIT_LIST_HEAD(&se->dobj.list);963 se->dobj.type = SND_SOC_DOBJ_ENUM;964 se->dobj.index = tplg->index;965 if (tplg->ops)966 se->dobj.unload = tplg->ops->control_unload;967 968 /* create control directly */969 ret = soc_tplg_add_kcontrol(tplg, &kc, &se->dobj.control.kcontrol);970 if (ret < 0)971 return ret;972 973 list_add(&se->dobj.list, &tplg->comp->dobj_list);974 975 return ret;976}977 978static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,979 struct snd_soc_tplg_hdr *hdr)980{981 int ret;982 int i;983 984 dev_dbg(tplg->dev, "ASoC: adding %d kcontrols at 0x%lx\n", hdr->count,985 soc_tplg_get_offset(tplg));986 987 for (i = 0; i < le32_to_cpu(hdr->count); i++) {988 struct snd_soc_tplg_ctl_hdr *control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;989 990 if (le32_to_cpu(control_hdr->size) != sizeof(*control_hdr)) {991 dev_err(tplg->dev, "ASoC: invalid control size\n");992 return -EINVAL;993 }994 995 switch (le32_to_cpu(control_hdr->ops.info)) {996 case SND_SOC_TPLG_CTL_VOLSW:997 case SND_SOC_TPLG_CTL_STROBE:998 case SND_SOC_TPLG_CTL_VOLSW_SX:999 case SND_SOC_TPLG_CTL_VOLSW_XR_SX:1000 case SND_SOC_TPLG_CTL_RANGE:1001 case SND_SOC_TPLG_DAPM_CTL_VOLSW:1002 case SND_SOC_TPLG_DAPM_CTL_PIN:1003 ret = soc_tplg_dmixer_create(tplg, le32_to_cpu(hdr->payload_size));1004 break;1005 case SND_SOC_TPLG_CTL_ENUM:1006 case SND_SOC_TPLG_CTL_ENUM_VALUE:1007 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:1008 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:1009 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:1010 ret = soc_tplg_denum_create(tplg, le32_to_cpu(hdr->payload_size));1011 break;1012 case SND_SOC_TPLG_CTL_BYTES:1013 ret = soc_tplg_dbytes_create(tplg, le32_to_cpu(hdr->payload_size));1014 break;1015 default:1016 soc_bind_err(tplg, control_hdr, i);1017 return -EINVAL;1018 }1019 if (ret < 0) {1020 dev_err(tplg->dev, "ASoC: invalid control\n");1021 return ret;1022 }1023 1024 }1025 1026 return 0;1027}1028 1029/* optionally pass new dynamic kcontrol to component driver. */1030static int soc_tplg_add_route(struct soc_tplg *tplg,1031 struct snd_soc_dapm_route *route)1032{1033 if (tplg->ops && tplg->ops->dapm_route_load)1034 return tplg->ops->dapm_route_load(tplg->comp, tplg->index,1035 route);1036 1037 return 0;1038}1039 1040static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,1041 struct snd_soc_tplg_hdr *hdr)1042{1043 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;1044 const size_t maxlen = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;1045 struct snd_soc_tplg_dapm_graph_elem *elem;1046 struct snd_soc_dapm_route *route;1047 int count, i;1048 int ret = 0;1049 1050 count = le32_to_cpu(hdr->count);1051 1052 if (soc_tplg_check_elem_count(tplg,1053 sizeof(struct snd_soc_tplg_dapm_graph_elem),1054 count, le32_to_cpu(hdr->payload_size), "graph"))1055 return -EINVAL;1056 1057 dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes for index %d\n", count,1058 hdr->index);1059 1060 for (i = 0; i < count; i++) {1061 route = devm_kzalloc(tplg->dev, sizeof(*route), GFP_KERNEL);1062 if (!route)1063 return -ENOMEM;1064 elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos;1065 tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem);1066 1067 /* validate routes */1068 if ((strnlen(elem->source, maxlen) == maxlen) ||1069 (strnlen(elem->sink, maxlen) == maxlen) ||1070 (strnlen(elem->control, maxlen) == maxlen)) {1071 ret = -EINVAL;1072 break;1073 }1074 1075 route->source = devm_kstrdup(tplg->dev, elem->source, GFP_KERNEL);1076 route->sink = devm_kstrdup(tplg->dev, elem->sink, GFP_KERNEL);1077 if (!route->source || !route->sink) {1078 ret = -ENOMEM;1079 break;1080 }1081 1082 if (strnlen(elem->control, maxlen) != 0) {1083 route->control = devm_kstrdup(tplg->dev, elem->control, GFP_KERNEL);1084 if (!route->control) {1085 ret = -ENOMEM;1086 break;1087 }1088 }1089 1090 /* add route dobj to dobj_list */1091 route->dobj.type = SND_SOC_DOBJ_GRAPH;1092 if (tplg->ops)1093 route->dobj.unload = tplg->ops->dapm_route_unload;1094 route->dobj.index = tplg->index;1095 list_add(&route->dobj.list, &tplg->comp->dobj_list);1096 1097 ret = soc_tplg_add_route(tplg, route);1098 if (ret < 0) {1099 dev_err(tplg->dev, "ASoC: topology: add_route failed: %d\n", ret);1100 break;1101 }1102 1103 ret = snd_soc_dapm_add_routes(dapm, route, 1);1104 if (ret) {1105 if (!dapm->card->disable_route_checks) {1106 dev_err(tplg->dev, "ASoC: dapm_add_routes failed: %d\n", ret);1107 break;1108 }1109 dev_info(tplg->dev,1110 "ASoC: disable_route_checks set, ignoring dapm_add_routes errors\n");1111 }1112 }1113 1114 return ret;1115}1116 1117static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg,1118 struct snd_soc_tplg_dapm_widget *w)1119{1120 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;1121 struct snd_soc_dapm_widget template, *widget;1122 struct snd_soc_tplg_ctl_hdr *control_hdr;1123 struct snd_soc_card *card = tplg->comp->card;1124 unsigned int *kcontrol_type = NULL;1125 struct snd_kcontrol_new *kc;1126 int mixer_count = 0;1127 int bytes_count = 0;1128 int enum_count = 0;1129 int ret = 0;1130 int i;1131 1132 if (strnlen(w->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==1133 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)1134 return -EINVAL;1135 if (strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==1136 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)1137 return -EINVAL;1138 1139 dev_dbg(tplg->dev, "ASoC: creating DAPM widget %s id %d\n",1140 w->name, w->id);1141 1142 memset(&template, 0, sizeof(template));1143 1144 /* map user to kernel widget ID */1145 template.id = get_widget_id(le32_to_cpu(w->id));1146 if ((int)template.id < 0)1147 return template.id;1148 1149 /* strings are allocated here, but used and freed by the widget */1150 template.name = kstrdup(w->name, GFP_KERNEL);1151 if (!template.name)1152 return -ENOMEM;1153 template.sname = kstrdup(w->sname, GFP_KERNEL);1154 if (!template.sname) {1155 ret = -ENOMEM;1156 goto err;1157 }1158 template.reg = le32_to_cpu(w->reg);1159 template.shift = le32_to_cpu(w->shift);1160 template.mask = le32_to_cpu(w->mask);1161 template.subseq = le32_to_cpu(w->subseq);1162 template.on_val = w->invert ? 0 : 1;1163 template.off_val = w->invert ? 1 : 0;1164 template.ignore_suspend = le32_to_cpu(w->ignore_suspend);1165 template.event_flags = le16_to_cpu(w->event_flags);1166 template.dobj.index = tplg->index;1167 1168 tplg->pos +=1169 (sizeof(struct snd_soc_tplg_dapm_widget) +1170 le32_to_cpu(w->priv.size));1171 1172 if (w->num_kcontrols == 0) {1173 template.num_kcontrols = 0;1174 goto widget;1175 }1176 1177 template.num_kcontrols = le32_to_cpu(w->num_kcontrols);1178 kc = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(*kc), GFP_KERNEL);1179 if (!kc) {1180 ret = -ENOMEM;1181 goto hdr_err;1182 }1183 1184 kcontrol_type = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(unsigned int),1185 GFP_KERNEL);1186 if (!kcontrol_type) {1187 ret = -ENOMEM;1188 goto hdr_err;1189 }1190 1191 for (i = 0; i < le32_to_cpu(w->num_kcontrols); i++) {1192 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;1193 switch (le32_to_cpu(control_hdr->ops.info)) {1194 case SND_SOC_TPLG_CTL_VOLSW:1195 case SND_SOC_TPLG_CTL_STROBE:1196 case SND_SOC_TPLG_CTL_VOLSW_SX:1197 case SND_SOC_TPLG_CTL_VOLSW_XR_SX:1198 case SND_SOC_TPLG_CTL_RANGE:1199 case SND_SOC_TPLG_DAPM_CTL_VOLSW:1200 /* volume mixer */1201 kc[i].index = mixer_count;1202 kcontrol_type[i] = SND_SOC_TPLG_TYPE_MIXER;1203 mixer_count++;1204 ret = soc_tplg_control_dmixer_create(tplg, &kc[i]);1205 if (ret < 0)1206 goto hdr_err;1207 break;1208 case SND_SOC_TPLG_CTL_ENUM:1209 case SND_SOC_TPLG_CTL_ENUM_VALUE:1210 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:1211 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:1212 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:1213 /* enumerated mixer */1214 kc[i].index = enum_count;1215 kcontrol_type[i] = SND_SOC_TPLG_TYPE_ENUM;1216 enum_count++;1217 ret = soc_tplg_control_denum_create(tplg, &kc[i]);1218 if (ret < 0)1219 goto hdr_err;1220 break;1221 case SND_SOC_TPLG_CTL_BYTES:1222 /* bytes control */1223 kc[i].index = bytes_count;1224 kcontrol_type[i] = SND_SOC_TPLG_TYPE_BYTES;1225 bytes_count++;1226 ret = soc_tplg_control_dbytes_create(tplg, &kc[i]);1227 if (ret < 0)1228 goto hdr_err;1229 break;1230 default:1231 dev_err(tplg->dev, "ASoC: invalid widget control type %d:%d:%d\n",1232 control_hdr->ops.get, control_hdr->ops.put,1233 le32_to_cpu(control_hdr->ops.info));1234 ret = -EINVAL;1235 goto hdr_err;1236 }1237 }1238 1239 template.kcontrol_news = kc;1240 dev_dbg(tplg->dev, "ASoC: template %s with %d/%d/%d (mixer/enum/bytes) control\n",1241 w->name, mixer_count, enum_count, bytes_count);1242 1243widget:1244 ret = soc_tplg_widget_load(tplg, &template, w);1245 if (ret < 0)1246 goto hdr_err;1247 1248 /* card dapm mutex is held by the core if we are loading topology1249 * data during sound card init. */1250 if (snd_soc_card_is_instantiated(card))1251 widget = snd_soc_dapm_new_control(dapm, &template);1252 else1253 widget = snd_soc_dapm_new_control_unlocked(dapm, &template);1254 if (IS_ERR(widget)) {1255 ret = PTR_ERR(widget);1256 goto hdr_err;1257 }1258 1259 widget->dobj.type = SND_SOC_DOBJ_WIDGET;1260 widget->dobj.widget.kcontrol_type = kcontrol_type;1261 if (tplg->ops)1262 widget->dobj.unload = tplg->ops->widget_unload;1263 widget->dobj.index = tplg->index;1264 list_add(&widget->dobj.list, &tplg->comp->dobj_list);1265 1266 ret = soc_tplg_widget_ready(tplg, widget, w);1267 if (ret < 0)1268 goto ready_err;1269 1270 kfree(template.sname);1271 kfree(template.name);1272 1273 return 0;1274 1275ready_err:1276 soc_tplg_remove_widget(widget->dapm->component, &widget->dobj, SOC_TPLG_PASS_WIDGET);1277 snd_soc_dapm_free_widget(widget);1278hdr_err:1279 kfree(template.sname);1280err:1281 kfree(template.name);1282 return ret;1283}1284 1285static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg,1286 struct snd_soc_tplg_hdr *hdr)1287{1288 int count, i;1289 1290 count = le32_to_cpu(hdr->count);1291 1292 dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count);1293 1294 for (i = 0; i < count; i++) {1295 struct snd_soc_tplg_dapm_widget *widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;1296 int ret;1297 1298 /*1299 * check if widget itself fits within topology file1300 * use sizeof instead of widget->size, as we can't be sure1301 * it is set properly yet (file may end before it is present)1302 */1303 if (soc_tplg_get_offset(tplg) + sizeof(*widget) >= tplg->fw->size) {1304 dev_err(tplg->dev, "ASoC: invalid widget data size\n");1305 return -EINVAL;1306 }1307 1308 /* check if widget has proper size */1309 if (le32_to_cpu(widget->size) != sizeof(*widget)) {1310 dev_err(tplg->dev, "ASoC: invalid widget size\n");1311 return -EINVAL;1312 }1313 1314 /* check if widget private data fits within topology file */1315 if (soc_tplg_get_offset(tplg) + le32_to_cpu(widget->priv.size) >= tplg->fw->size) {1316 dev_err(tplg->dev, "ASoC: invalid widget private data size\n");1317 return -EINVAL;1318 }1319 1320 ret = soc_tplg_dapm_widget_create(tplg, widget);1321 if (ret < 0) {1322 dev_err(tplg->dev, "ASoC: failed to load widget %s\n",1323 widget->name);1324 return ret;1325 }1326 }1327 1328 return 0;1329}1330 1331static int soc_tplg_dapm_complete(struct soc_tplg *tplg)1332{1333 struct snd_soc_card *card = tplg->comp->card;1334 int ret;1335 1336 /* Card might not have been registered at this point.1337 * If so, just return success.1338 */1339 if (!snd_soc_card_is_instantiated(card)) {1340 dev_warn(tplg->dev, "ASoC: Parent card not yet available, widget card binding deferred\n");1341 return 0;1342 }1343 1344 ret = snd_soc_dapm_new_widgets(card);1345 if (ret < 0)1346 dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n", ret);1347 1348 return ret;1349}1350 1351static int set_stream_info(struct soc_tplg *tplg, struct snd_soc_pcm_stream *stream,1352 struct snd_soc_tplg_stream_caps *caps)1353{1354 stream->stream_name = devm_kstrdup(tplg->dev, caps->name, GFP_KERNEL);1355 if (!stream->stream_name)1356 return -ENOMEM;1357 1358 stream->channels_min = le32_to_cpu(caps->channels_min);1359 stream->channels_max = le32_to_cpu(caps->channels_max);1360 stream->rates = le32_to_cpu(caps->rates);1361 stream->rate_min = le32_to_cpu(caps->rate_min);1362 stream->rate_max = le32_to_cpu(caps->rate_max);1363 stream->formats = le64_to_cpu(caps->formats);1364 stream->sig_bits = le32_to_cpu(caps->sig_bits);1365 1366 return 0;1367}1368 1369static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,1370 unsigned int flag_mask, unsigned int flags)1371{1372 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES)1373 dai_drv->symmetric_rate =1374 (flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES) ? 1 : 0;1375 1376 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS)1377 dai_drv->symmetric_channels =1378 (flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS) ?1379 1 : 0;1380 1381 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS)1382 dai_drv->symmetric_sample_bits =1383 (flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS) ?1384 1 : 0;1385}1386 1387static const struct snd_soc_dai_ops tplg_dai_ops = {1388 .compress_new = snd_soc_new_compress,1389};1390 1391static int soc_tplg_dai_create(struct soc_tplg *tplg,1392 struct snd_soc_tplg_pcm *pcm)1393{1394 struct snd_soc_dai_driver *dai_drv;1395 struct snd_soc_pcm_stream *stream;1396 struct snd_soc_tplg_stream_caps *caps;1397 struct snd_soc_dai *dai;1398 struct snd_soc_dapm_context *dapm =1399 snd_soc_component_get_dapm(tplg->comp);1400 int ret;1401 1402 dai_drv = devm_kzalloc(tplg->dev, sizeof(struct snd_soc_dai_driver), GFP_KERNEL);1403 if (dai_drv == NULL)1404 return -ENOMEM;1405 1406 if (strlen(pcm->dai_name)) {1407 dai_drv->name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL);1408 if (!dai_drv->name) {1409 ret = -ENOMEM;1410 goto err;1411 }1412 }1413 dai_drv->id = le32_to_cpu(pcm->dai_id);1414 1415 if (pcm->playback) {1416 stream = &dai_drv->playback;1417 caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK];1418 ret = set_stream_info(tplg, stream, caps);1419 if (ret < 0)1420 goto err;1421 }1422 1423 if (pcm->capture) {1424 stream = &dai_drv->capture;1425 caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE];1426 ret = set_stream_info(tplg, stream, caps);1427 if (ret < 0)1428 goto err;1429 }1430 1431 if (pcm->compress)1432 dai_drv->ops = &tplg_dai_ops;1433 1434 /* pass control to component driver for optional further init */1435 ret = soc_tplg_dai_load(tplg, dai_drv, pcm, NULL);1436 if (ret < 0) {1437 dev_err(tplg->dev, "ASoC: DAI loading failed\n");1438 goto err;1439 }1440 1441 dai_drv->dobj.index = tplg->index;1442 dai_drv->dobj.type = SND_SOC_DOBJ_PCM;1443 if (tplg->ops)1444 dai_drv->dobj.unload = tplg->ops->dai_unload;1445 list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list);1446 1447 /* register the DAI to the component */1448 dai = snd_soc_register_dai(tplg->comp, dai_drv, false);1449 if (!dai)1450 return -ENOMEM;1451 1452 /* Create the DAI widgets here */1453 ret = snd_soc_dapm_new_dai_widgets(dapm, dai);1454 if (ret != 0) {1455 dev_err(dai->dev, "Failed to create DAI widgets %d\n", ret);1456 snd_soc_unregister_dai(dai);1457 return ret;1458 }1459 1460 return 0;1461 1462err:1463 return ret;1464}1465 1466static void set_link_flags(struct snd_soc_dai_link *link,1467 unsigned int flag_mask, unsigned int flags)1468{1469 if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES)1470 link->symmetric_rate =1471 (flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES) ? 1 : 0;1472 1473 if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS)1474 link->symmetric_channels =1475 (flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS) ?1476 1 : 0;1477 1478 if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS)1479 link->symmetric_sample_bits =1480 (flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS) ?1481 1 : 0;1482 1483 if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP)1484 link->ignore_suspend =1485 (flags & SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP) ?1486 1 : 0;1487}1488 1489/* create the FE DAI link */1490static int soc_tplg_fe_link_create(struct soc_tplg *tplg,1491 struct snd_soc_tplg_pcm *pcm)1492{1493 struct snd_soc_dai_link *link;1494 struct snd_soc_dai_link_component *dlc;1495 int ret;1496 1497 /* link + cpu + codec + platform */1498 link = devm_kzalloc(tplg->dev, sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL);1499 if (link == NULL)1500 return -ENOMEM;1501 1502 dlc = (struct snd_soc_dai_link_component *)(link + 1);1503 1504 link->cpus = &dlc[0];1505 link->num_cpus = 1;1506 1507 link->dobj.index = tplg->index;1508 link->dobj.type = SND_SOC_DOBJ_DAI_LINK;1509 if (tplg->ops)1510 link->dobj.unload = tplg->ops->link_unload;1511 1512 if (strlen(pcm->pcm_name)) {1513 link->name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL);1514 link->stream_name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL);1515 if (!link->name || !link->stream_name) {1516 ret = -ENOMEM;1517 goto err;1518 }1519 }1520 link->id = le32_to_cpu(pcm->pcm_id);1521 1522 if (strlen(pcm->dai_name)) {1523 link->cpus->dai_name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL);1524 if (!link->cpus->dai_name) {1525 ret = -ENOMEM;1526 goto err;1527 }1528 }1529 1530 /*1531 * Many topology are assuming link has Codec / Platform, and1532 * these might be overwritten at soc_tplg_dai_link_load().1533 * Don't use &snd_soc_dummy_dlc here.1534 */1535 link->codecs = &dlc[1]; /* Don't use &snd_soc_dummy_dlc here */1536 link->codecs->name = "snd-soc-dummy";1537 link->codecs->dai_name = "snd-soc-dummy-dai";1538 link->num_codecs = 1;1539 1540 link->platforms = &dlc[2]; /* Don't use &snd_soc_dummy_dlc here */1541 link->platforms->name = "snd-soc-dummy";1542 link->num_platforms = 1;1543 1544 /* enable DPCM */1545 link->dynamic = 1;1546 link->ignore_pmdown_time = 1;1547 link->dpcm_playback = le32_to_cpu(pcm->playback);1548 link->dpcm_capture = le32_to_cpu(pcm->capture);1549 if (pcm->flag_mask)1550 set_link_flags(link,1551 le32_to_cpu(pcm->flag_mask),1552 le32_to_cpu(pcm->flags));1553 1554 /* pass control to component driver for optional further init */1555 ret = soc_tplg_dai_link_load(tplg, link, NULL);1556 if (ret < 0) {1557 dev_err(tplg->dev, "ASoC: FE link loading failed\n");1558 goto err;1559 }1560 1561 ret = snd_soc_add_pcm_runtimes(tplg->comp->card, link, 1);1562 if (ret < 0) {1563 if (ret != -EPROBE_DEFER)1564 dev_err(tplg->dev, "ASoC: adding FE link failed\n");1565 goto err;1566 }1567 1568 list_add(&link->dobj.list, &tplg->comp->dobj_list);1569 1570 return 0;1571err:1572 return ret;1573}1574 1575/* create a FE DAI and DAI link from the PCM object */1576static int soc_tplg_pcm_create(struct soc_tplg *tplg,1577 struct snd_soc_tplg_pcm *pcm)1578{1579 int ret;1580 1581 ret = soc_tplg_dai_create(tplg, pcm);1582 if (ret < 0)1583 return ret;1584 1585 return soc_tplg_fe_link_create(tplg, pcm);1586}1587 1588static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,1589 struct snd_soc_tplg_hdr *hdr)1590{1591 struct snd_soc_tplg_pcm *pcm;1592 int count;1593 int size;1594 int i;1595 int ret;1596 1597 count = le32_to_cpu(hdr->count);1598 1599 /* check the element size and count */1600 pcm = (struct snd_soc_tplg_pcm *)tplg->pos;1601 size = le32_to_cpu(pcm->size);1602 if (size > sizeof(struct snd_soc_tplg_pcm)) {1603 dev_err(tplg->dev, "ASoC: invalid size %d for PCM elems\n",1604 size);1605 return -EINVAL;1606 }1607 1608 if (soc_tplg_check_elem_count(tplg,1609 size, count,1610 le32_to_cpu(hdr->payload_size),1611 "PCM DAI"))1612 return -EINVAL;1613 1614 for (i = 0; i < count; i++) {1615 pcm = (struct snd_soc_tplg_pcm *)tplg->pos;1616 size = le32_to_cpu(pcm->size);1617 1618 /* check ABI version by size, create a new version of pcm1619 * if abi not match.1620 */1621 if (size != sizeof(*pcm))1622 return -EINVAL;1623 1624 /* create the FE DAIs and DAI links */1625 ret = soc_tplg_pcm_create(tplg, pcm);1626 if (ret < 0)1627 return ret;1628 1629 /* offset by version-specific struct size and1630 * real priv data size1631 */1632 tplg->pos += size + le32_to_cpu(pcm->priv.size);1633 }1634 1635 dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count);1636 1637 return 0;1638}1639 1640/**1641 * set_link_hw_format - Set the HW audio format of the physical DAI link.1642 * @link: &snd_soc_dai_link which should be updated1643 * @cfg: physical link configs.1644 *1645 * Topology context contains a list of supported HW formats (configs) and1646 * a default format ID for the physical link. This function will use this1647 * default ID to choose the HW format to set the link's DAI format for init.1648 */1649static void set_link_hw_format(struct snd_soc_dai_link *link,1650 struct snd_soc_tplg_link_config *cfg)1651{1652 struct snd_soc_tplg_hw_config *hw_config;1653 unsigned char bclk_provider, fsync_provider;1654 unsigned char invert_bclk, invert_fsync;1655 int i;1656 1657 for (i = 0; i < le32_to_cpu(cfg->num_hw_configs); i++) {1658 hw_config = &cfg->hw_config[i];1659 if (hw_config->id != cfg->default_hw_config_id)1660 continue;1661 1662 link->dai_fmt = le32_to_cpu(hw_config->fmt) &1663 SND_SOC_DAIFMT_FORMAT_MASK;1664 1665 /* clock gating */1666 switch (hw_config->clock_gated) {1667 case SND_SOC_TPLG_DAI_CLK_GATE_GATED:1668 link->dai_fmt |= SND_SOC_DAIFMT_GATED;1669 break;1670 1671 case SND_SOC_TPLG_DAI_CLK_GATE_CONT:1672 link->dai_fmt |= SND_SOC_DAIFMT_CONT;1673 break;1674 1675 default:1676 /* ignore the value */1677 break;1678 }1679 1680 /* clock signal polarity */1681 invert_bclk = hw_config->invert_bclk;1682 invert_fsync = hw_config->invert_fsync;1683 if (!invert_bclk && !invert_fsync)1684 link->dai_fmt |= SND_SOC_DAIFMT_NB_NF;1685 else if (!invert_bclk && invert_fsync)1686 link->dai_fmt |= SND_SOC_DAIFMT_NB_IF;1687 else if (invert_bclk && !invert_fsync)1688 link->dai_fmt |= SND_SOC_DAIFMT_IB_NF;1689 else1690 link->dai_fmt |= SND_SOC_DAIFMT_IB_IF;1691 1692 /* clock masters */1693 bclk_provider = (hw_config->bclk_provider ==1694 SND_SOC_TPLG_BCLK_CP);1695 fsync_provider = (hw_config->fsync_provider ==1696 SND_SOC_TPLG_FSYNC_CP);1697 if (bclk_provider && fsync_provider)1698 link->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;1699 else if (!bclk_provider && fsync_provider)1700 link->dai_fmt |= SND_SOC_DAIFMT_CBC_CFP;1701 else if (bclk_provider && !fsync_provider)1702 link->dai_fmt |= SND_SOC_DAIFMT_CBP_CFC;1703 else1704 link->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC;1705 }1706}1707 1708/**1709 * snd_soc_find_dai_link - Find a DAI link1710 *1711 * @card: soc card1712 * @id: DAI link ID to match1713 * @name: DAI link name to match, optional1714 * @stream_name: DAI link stream name to match, optional1715 *1716 * This function will search all existing DAI links of the soc card to1717 * find the link of the same ID. Since DAI links may not have their1718 * unique ID, so name and stream name should also match if being1719 * specified.1720 *1721 * Return: pointer of DAI link, or NULL if not found.1722 */1723static struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card,1724 int id, const char *name,1725 const char *stream_name)1726{1727 struct snd_soc_pcm_runtime *rtd;1728 1729 for_each_card_rtds(card, rtd) {1730 struct snd_soc_dai_link *link = rtd->dai_link;1731 1732 if (link->id != id)1733 continue;1734 1735 if (name && (!link->name || !strstr(link->name, name)))1736 continue;1737 1738 if (stream_name && (!link->stream_name ||1739 !strstr(link->stream_name, stream_name)))1740 continue;1741 1742 return link;1743 }1744 1745 return NULL;1746}1747 1748/* Find and configure an existing physical DAI link */1749static int soc_tplg_link_config(struct soc_tplg *tplg,1750 struct snd_soc_tplg_link_config *cfg)1751{1752 struct snd_soc_dai_link *link;1753 const char *name, *stream_name;1754 size_t len;1755 int ret;1756 1757 len = strnlen(cfg->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);1758 if (len == SNDRV_CTL_ELEM_ID_NAME_MAXLEN)1759 return -EINVAL;1760 else if (len)1761 name = cfg->name;1762 else1763 name = NULL;1764 1765 len = strnlen(cfg->stream_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);1766 if (len == SNDRV_CTL_ELEM_ID_NAME_MAXLEN)1767 return -EINVAL;1768 else if (len)1769 stream_name = cfg->stream_name;1770 else1771 stream_name = NULL;1772 1773 link = snd_soc_find_dai_link(tplg->comp->card, le32_to_cpu(cfg->id),1774 name, stream_name);1775 if (!link) {1776 dev_err(tplg->dev, "ASoC: physical link %s (id %d) not exist\n",1777 name, cfg->id);1778 return -EINVAL;1779 }1780 1781 /* hw format */1782 if (cfg->num_hw_configs)1783 set_link_hw_format(link, cfg);1784 1785 /* flags */1786 if (cfg->flag_mask)1787 set_link_flags(link,1788 le32_to_cpu(cfg->flag_mask),1789 le32_to_cpu(cfg->flags));1790 1791 /* pass control to component driver for optional further init */1792 ret = soc_tplg_dai_link_load(tplg, link, cfg);1793 if (ret < 0) {1794 dev_err(tplg->dev, "ASoC: physical link loading failed\n");1795 return ret;1796 }1797 1798 /* for unloading it in snd_soc_tplg_component_remove */1799 link->dobj.index = tplg->index;1800 link->dobj.type = SND_SOC_DOBJ_BACKEND_LINK;1801 if (tplg->ops)1802 link->dobj.unload = tplg->ops->link_unload;1803 list_add(&link->dobj.list, &tplg->comp->dobj_list);1804 1805 return 0;1806}1807 1808 1809/* Load physical link config elements from the topology context */1810static int soc_tplg_link_elems_load(struct soc_tplg *tplg,1811 struct snd_soc_tplg_hdr *hdr)1812{1813 struct snd_soc_tplg_link_config *link;1814 int count;1815 int size;1816 int i, ret;1817 1818 count = le32_to_cpu(hdr->count);1819 1820 /* check the element size and count */1821 link = (struct snd_soc_tplg_link_config *)tplg->pos;1822 size = le32_to_cpu(link->size);1823 if (size > sizeof(struct snd_soc_tplg_link_config)) {1824 dev_err(tplg->dev, "ASoC: invalid size %d for physical link elems\n",1825 size);1826 return -EINVAL;1827 }1828 1829 if (soc_tplg_check_elem_count(tplg, size, count,1830 le32_to_cpu(hdr->payload_size),1831 "physical link config"))1832 return -EINVAL;1833 1834 /* config physical DAI links */1835 for (i = 0; i < count; i++) {1836 link = (struct snd_soc_tplg_link_config *)tplg->pos;1837 size = le32_to_cpu(link->size);1838 if (size != sizeof(*link))1839 return -EINVAL;1840 1841 ret = soc_tplg_link_config(tplg, link);1842 if (ret < 0)1843 return ret;1844 1845 /* offset by version-specific struct size and1846 * real priv data size1847 */1848 tplg->pos += size + le32_to_cpu(link->priv.size);1849 }1850 1851 return 0;1852}1853 1854/**1855 * soc_tplg_dai_config - Find and configure an existing physical DAI.1856 * @tplg: topology context1857 * @d: physical DAI configs.1858 *1859 * The physical dai should already be registered by the platform driver.1860 * The platform driver should specify the DAI name and ID for matching.1861 */1862static int soc_tplg_dai_config(struct soc_tplg *tplg,1863 struct snd_soc_tplg_dai *d)1864{1865 struct snd_soc_dai_link_component dai_component;1866 struct snd_soc_dai *dai;1867 struct snd_soc_dai_driver *dai_drv;1868 struct snd_soc_pcm_stream *stream;1869 struct snd_soc_tplg_stream_caps *caps;1870 int ret;1871 1872 memset(&dai_component, 0, sizeof(dai_component));1873 1874 dai_component.dai_name = d->dai_name;1875 dai = snd_soc_find_dai(&dai_component);1876 if (!dai) {1877 dev_err(tplg->dev, "ASoC: physical DAI %s not registered\n",1878 d->dai_name);1879 return -EINVAL;1880 }1881 1882 if (le32_to_cpu(d->dai_id) != dai->id) {1883 dev_err(tplg->dev, "ASoC: physical DAI %s id mismatch\n",1884 d->dai_name);1885 return -EINVAL;1886 }1887 1888 dai_drv = dai->driver;1889 if (!dai_drv)1890 return -EINVAL;1891 1892 if (d->playback) {1893 stream = &dai_drv->playback;1894 caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK];1895 ret = set_stream_info(tplg, stream, caps);1896 if (ret < 0)1897 return ret;1898 }1899 1900 if (d->capture) {1901 stream = &dai_drv->capture;1902 caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE];1903 ret = set_stream_info(tplg, stream, caps);1904 if (ret < 0)1905 return ret;1906 }1907 1908 if (d->flag_mask)1909 set_dai_flags(dai_drv,1910 le32_to_cpu(d->flag_mask),1911 le32_to_cpu(d->flags));1912 1913 /* pass control to component driver for optional further init */1914 ret = soc_tplg_dai_load(tplg, dai_drv, NULL, dai);1915 if (ret < 0) {1916 dev_err(tplg->dev, "ASoC: DAI loading failed\n");1917 return ret;1918 }1919 1920 return 0;1921}1922 1923/* load physical DAI elements */1924static int soc_tplg_dai_elems_load(struct soc_tplg *tplg,1925 struct snd_soc_tplg_hdr *hdr)1926{1927 int count;1928 int i;1929 1930 count = le32_to_cpu(hdr->count);1931 1932 /* config the existing BE DAIs */1933 for (i = 0; i < count; i++) {1934 struct snd_soc_tplg_dai *dai = (struct snd_soc_tplg_dai *)tplg->pos;1935 int ret;1936 1937 if (le32_to_cpu(dai->size) != sizeof(*dai)) {1938 dev_err(tplg->dev, "ASoC: invalid physical DAI size\n");1939 return -EINVAL;1940 }1941 1942 ret = soc_tplg_dai_config(tplg, dai);1943 if (ret < 0) {1944 dev_err(tplg->dev, "ASoC: failed to configure DAI\n");1945 return ret;1946 }1947 1948 tplg->pos += (sizeof(*dai) + le32_to_cpu(dai->priv.size));1949 }1950 1951 dev_dbg(tplg->dev, "ASoC: Configure %d BE DAIs\n", count);1952 return 0;1953}1954 1955static int soc_tplg_manifest_load(struct soc_tplg *tplg,1956 struct snd_soc_tplg_hdr *hdr)1957{1958 struct snd_soc_tplg_manifest *manifest;1959 int ret = 0;1960 1961 manifest = (struct snd_soc_tplg_manifest *)tplg->pos;1962 1963 /* check ABI version by size, create a new manifest if abi not match */1964 if (le32_to_cpu(manifest->size) != sizeof(*manifest))1965 return -EINVAL;1966 1967 /* pass control to component driver for optional further init */1968 if (tplg->ops && tplg->ops->manifest)1969 ret = tplg->ops->manifest(tplg->comp, tplg->index, manifest);1970 1971 return ret;1972}1973 1974/* validate header magic, size and type */1975static int soc_tplg_valid_header(struct soc_tplg *tplg,1976 struct snd_soc_tplg_hdr *hdr)1977{1978 if (le32_to_cpu(hdr->size) != sizeof(*hdr)) {1979 dev_err(tplg->dev,1980 "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n",1981 le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg),1982 tplg->fw->size);1983 return -EINVAL;1984 }1985 1986 if (soc_tplg_get_hdr_offset(tplg) + le32_to_cpu(hdr->payload_size) >= tplg->fw->size) {1987 dev_err(tplg->dev,1988 "ASoC: invalid header of type %d at offset %ld payload_size %d\n",1989 le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg),1990 hdr->payload_size);1991 return -EINVAL;1992 }1993 1994 /* big endian firmware objects not supported atm */1995 if (le32_to_cpu(hdr->magic) == SOC_TPLG_MAGIC_BIG_ENDIAN) {1996 dev_err(tplg->dev,1997 "ASoC: pass %d big endian not supported header got %x at offset 0x%lx size 0x%zx.\n",1998 tplg->pass, hdr->magic,1999 soc_tplg_get_hdr_offset(tplg), tplg->fw->size);2000 return -EINVAL;2001 }2002 2003 if (le32_to_cpu(hdr->magic) != SND_SOC_TPLG_MAGIC) {2004 dev_err(tplg->dev,2005 "ASoC: pass %d does not have a valid header got %x at offset 0x%lx size 0x%zx.\n",2006 tplg->pass, hdr->magic,2007 soc_tplg_get_hdr_offset(tplg), tplg->fw->size);2008 return -EINVAL;2009 }2010 2011 /* Support ABI from version 4 */2012 if (le32_to_cpu(hdr->abi) > SND_SOC_TPLG_ABI_VERSION ||2013 le32_to_cpu(hdr->abi) < SND_SOC_TPLG_ABI_VERSION_MIN) {2014 dev_err(tplg->dev,2015 "ASoC: pass %d invalid ABI version got 0x%x need 0x%x at offset 0x%lx size 0x%zx.\n",2016 tplg->pass, hdr->abi,2017 SND_SOC_TPLG_ABI_VERSION, soc_tplg_get_hdr_offset(tplg),2018 tplg->fw->size);2019 return -EINVAL;2020 }2021 2022 if (hdr->payload_size == 0) {2023 dev_err(tplg->dev, "ASoC: header has 0 size at offset 0x%lx.\n",2024 soc_tplg_get_hdr_offset(tplg));2025 return -EINVAL;2026 }2027 2028 return 0;2029}2030 2031/* check header type and call appropriate handler */2032static int soc_tplg_load_header(struct soc_tplg *tplg,2033 struct snd_soc_tplg_hdr *hdr)2034{2035 int (*elem_load)(struct soc_tplg *tplg,2036 struct snd_soc_tplg_hdr *hdr);2037 unsigned int hdr_pass;2038 2039 tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr);2040 2041 tplg->index = le32_to_cpu(hdr->index);2042 2043 switch (le32_to_cpu(hdr->type)) {2044 case SND_SOC_TPLG_TYPE_MIXER:2045 case SND_SOC_TPLG_TYPE_ENUM:2046 case SND_SOC_TPLG_TYPE_BYTES:2047 hdr_pass = SOC_TPLG_PASS_CONTROL;2048 elem_load = soc_tplg_kcontrol_elems_load;2049 break;2050 case SND_SOC_TPLG_TYPE_DAPM_GRAPH:2051 hdr_pass = SOC_TPLG_PASS_GRAPH;2052 elem_load = soc_tplg_dapm_graph_elems_load;2053 break;2054 case SND_SOC_TPLG_TYPE_DAPM_WIDGET:2055 hdr_pass = SOC_TPLG_PASS_WIDGET;2056 elem_load = soc_tplg_dapm_widget_elems_load;2057 break;2058 case SND_SOC_TPLG_TYPE_PCM:2059 hdr_pass = SOC_TPLG_PASS_PCM_DAI;2060 elem_load = soc_tplg_pcm_elems_load;2061 break;2062 case SND_SOC_TPLG_TYPE_DAI:2063 hdr_pass = SOC_TPLG_PASS_BE_DAI;2064 elem_load = soc_tplg_dai_elems_load;2065 break;2066 case SND_SOC_TPLG_TYPE_DAI_LINK:2067 case SND_SOC_TPLG_TYPE_BACKEND_LINK:2068 /* physical link configurations */2069 hdr_pass = SOC_TPLG_PASS_LINK;2070 elem_load = soc_tplg_link_elems_load;2071 break;2072 case SND_SOC_TPLG_TYPE_MANIFEST:2073 hdr_pass = SOC_TPLG_PASS_MANIFEST;2074 elem_load = soc_tplg_manifest_load;2075 break;2076 default:2077 /* bespoke vendor data object */2078 hdr_pass = SOC_TPLG_PASS_VENDOR;2079 elem_load = soc_tplg_vendor_load;2080 break;2081 }2082 2083 if (tplg->pass == hdr_pass) {2084 dev_dbg(tplg->dev,2085 "ASoC: Got 0x%x bytes of type %d version %d vendor %d at pass %d\n",2086 hdr->payload_size, hdr->type, hdr->version,2087 hdr->vendor_type, tplg->pass);2088 return elem_load(tplg, hdr);2089 }2090 2091 return 0;2092}2093 2094/* process the topology file headers */2095static int soc_tplg_process_headers(struct soc_tplg *tplg)2096{2097 int ret;2098 2099 /* process the header types from start to end */2100 for (tplg->pass = SOC_TPLG_PASS_START; tplg->pass <= SOC_TPLG_PASS_END; tplg->pass++) {2101 struct snd_soc_tplg_hdr *hdr;2102 2103 tplg->hdr_pos = tplg->fw->data;2104 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;2105 2106 while (!soc_tplg_is_eof(tplg)) {2107 2108 /* make sure header is valid before loading */2109 ret = soc_tplg_valid_header(tplg, hdr);2110 if (ret < 0)2111 return ret;2112 2113 /* load the header object */2114 ret = soc_tplg_load_header(tplg, hdr);2115 if (ret < 0) {2116 if (ret != -EPROBE_DEFER) {2117 dev_err(tplg->dev,2118 "ASoC: topology: could not load header: %d\n",2119 ret);2120 }2121 return ret;2122 }2123 2124 /* goto next header */2125 tplg->hdr_pos += le32_to_cpu(hdr->payload_size) +2126 sizeof(struct snd_soc_tplg_hdr);2127 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;2128 }2129 2130 }2131 2132 /* signal DAPM we are complete */2133 ret = soc_tplg_dapm_complete(tplg);2134 2135 return ret;2136}2137 2138static int soc_tplg_load(struct soc_tplg *tplg)2139{2140 int ret;2141 2142 ret = soc_tplg_process_headers(tplg);2143 if (ret == 0)2144 return soc_tplg_complete(tplg);2145 2146 return ret;2147}2148 2149/* load audio component topology from "firmware" file */2150int snd_soc_tplg_component_load(struct snd_soc_component *comp,2151 const struct snd_soc_tplg_ops *ops, const struct firmware *fw)2152{2153 struct soc_tplg tplg;2154 int ret;2155 2156 /*2157 * check if we have sane parameters:2158 * comp - needs to exist to keep and reference data while parsing2159 * comp->card - used for setting card related parameters2160 * comp->card->dev - used for resource management and prints2161 * fw - we need it, as it is the very thing we parse2162 */2163 if (!comp || !comp->card || !comp->card->dev || !fw)2164 return -EINVAL;2165 2166 /* setup parsing context */2167 memset(&tplg, 0, sizeof(tplg));2168 tplg.fw = fw;2169 tplg.dev = comp->card->dev;2170 tplg.comp = comp;2171 if (ops) {2172 tplg.ops = ops;2173 tplg.io_ops = ops->io_ops;2174 tplg.io_ops_count = ops->io_ops_count;2175 tplg.bytes_ext_ops = ops->bytes_ext_ops;2176 tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;2177 }2178 2179 ret = soc_tplg_load(&tplg);2180 /* free the created components if fail to load topology */2181 if (ret)2182 snd_soc_tplg_component_remove(comp);2183 2184 return ret;2185}2186EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load);2187 2188/* remove dynamic controls from the component driver */2189int snd_soc_tplg_component_remove(struct snd_soc_component *comp)2190{2191 struct snd_soc_dobj *dobj, *next_dobj;2192 int pass;2193 2194 /* process the header types from end to start */2195 for (pass = SOC_TPLG_PASS_END; pass >= SOC_TPLG_PASS_START; pass--) {2196 2197 /* remove mixer controls */2198 list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list,2199 list) {2200 2201 switch (dobj->type) {2202 case SND_SOC_DOBJ_BYTES:2203 case SND_SOC_DOBJ_ENUM:2204 case SND_SOC_DOBJ_MIXER:2205 soc_tplg_remove_kcontrol(comp, dobj, pass);2206 break;2207 case SND_SOC_DOBJ_GRAPH:2208 soc_tplg_remove_route(comp, dobj, pass);2209 break;2210 case SND_SOC_DOBJ_WIDGET:2211 soc_tplg_remove_widget(comp, dobj, pass);2212 break;2213 case SND_SOC_DOBJ_PCM:2214 soc_tplg_remove_dai(comp, dobj, pass);2215 break;2216 case SND_SOC_DOBJ_DAI_LINK:2217 soc_tplg_remove_link(comp, dobj, pass);2218 break;2219 case SND_SOC_DOBJ_BACKEND_LINK:2220 /*2221 * call link_unload ops if extra2222 * deinitialization is needed.2223 */2224 remove_backend_link(comp, dobj, pass);2225 break;2226 default:2227 dev_err(comp->dev, "ASoC: invalid component type %d for removal\n",2228 dobj->type);2229 break;2230 }2231 }2232 }2233 2234 /* let caller know if FW can be freed when no objects are left */2235 return !list_empty(&comp->dobj_list);2236}2237EXPORT_SYMBOL_GPL(snd_soc_tplg_component_remove);2238