brintos

brintos / linux-shallow public Read only

0
0
Text · 60.2 KiB · 9751742 Raw
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