brintos

brintos / linux-shallow public Read only

0
0
Text · 123.8 KiB · 99521c7 Raw
4919 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management4//5// Copyright 2005 Wolfson Microelectronics PLC.6// Author: Liam Girdwood <lrg@slimlogic.co.uk>7//8//  Features:9//    o Changes power status of internal codec blocks depending on the10//      dynamic configuration of codec internal audio paths and active11//      DACs/ADCs.12//    o Platform power domain - can support external components i.e. amps and13//      mic/headphone insertion events.14//    o Automatic Mic Bias support15//    o Jack insertion power event initiation - e.g. hp insertion will enable16//      sinks, dacs, etc17//    o Delayed power down of audio subsystem to reduce pops between a quick18//      device reopen.19 20#include <linux/module.h>21#include <linux/init.h>22#include <linux/async.h>23#include <linux/cleanup.h>24#include <linux/delay.h>25#include <linux/pm.h>26#include <linux/bitops.h>27#include <linux/platform_device.h>28#include <linux/jiffies.h>29#include <linux/debugfs.h>30#include <linux/pm_runtime.h>31#include <linux/regulator/consumer.h>32#include <linux/pinctrl/consumer.h>33#include <linux/clk.h>34#include <linux/slab.h>35#include <sound/core.h>36#include <sound/pcm.h>37#include <sound/pcm_params.h>38#include <sound/soc.h>39#include <sound/initval.h>40 41#include <trace/events/asoc.h>42 43#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;44 45#define SND_SOC_DAPM_DIR_REVERSE(x) ((x == SND_SOC_DAPM_DIR_IN) ? \46	SND_SOC_DAPM_DIR_OUT : SND_SOC_DAPM_DIR_IN)47 48#define snd_soc_dapm_for_each_direction(dir) \49	for ((dir) = SND_SOC_DAPM_DIR_IN; (dir) <= SND_SOC_DAPM_DIR_OUT; \50		(dir)++)51 52static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,53	struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,54	const char *control,55	int (*connected)(struct snd_soc_dapm_widget *source,56			 struct snd_soc_dapm_widget *sink));57 58struct snd_soc_dapm_widget *59snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,60			 const struct snd_soc_dapm_widget *widget);61 62struct snd_soc_dapm_widget *63snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,64			 const struct snd_soc_dapm_widget *widget);65 66static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg);67 68/* dapm power sequences - make this per codec in the future */69static int dapm_up_seq[] = {70	[snd_soc_dapm_pre] = 1,71	[snd_soc_dapm_regulator_supply] = 2,72	[snd_soc_dapm_pinctrl] = 2,73	[snd_soc_dapm_clock_supply] = 2,74	[snd_soc_dapm_supply] = 3,75	[snd_soc_dapm_dai_link] = 3,76	[snd_soc_dapm_micbias] = 4,77	[snd_soc_dapm_vmid] = 4,78	[snd_soc_dapm_dai_in] = 5,79	[snd_soc_dapm_dai_out] = 5,80	[snd_soc_dapm_aif_in] = 5,81	[snd_soc_dapm_aif_out] = 5,82	[snd_soc_dapm_mic] = 6,83	[snd_soc_dapm_siggen] = 6,84	[snd_soc_dapm_input] = 6,85	[snd_soc_dapm_output] = 6,86	[snd_soc_dapm_mux] = 7,87	[snd_soc_dapm_demux] = 7,88	[snd_soc_dapm_dac] = 8,89	[snd_soc_dapm_switch] = 9,90	[snd_soc_dapm_mixer] = 9,91	[snd_soc_dapm_mixer_named_ctl] = 9,92	[snd_soc_dapm_pga] = 10,93	[snd_soc_dapm_buffer] = 10,94	[snd_soc_dapm_scheduler] = 10,95	[snd_soc_dapm_effect] = 10,96	[snd_soc_dapm_src] = 10,97	[snd_soc_dapm_asrc] = 10,98	[snd_soc_dapm_encoder] = 10,99	[snd_soc_dapm_decoder] = 10,100	[snd_soc_dapm_adc] = 11,101	[snd_soc_dapm_out_drv] = 12,102	[snd_soc_dapm_hp] = 12,103	[snd_soc_dapm_line] = 12,104	[snd_soc_dapm_sink] = 12,105	[snd_soc_dapm_spk] = 13,106	[snd_soc_dapm_kcontrol] = 14,107	[snd_soc_dapm_post] = 15,108};109 110static int dapm_down_seq[] = {111	[snd_soc_dapm_pre] = 1,112	[snd_soc_dapm_kcontrol] = 2,113	[snd_soc_dapm_adc] = 3,114	[snd_soc_dapm_spk] = 4,115	[snd_soc_dapm_hp] = 5,116	[snd_soc_dapm_line] = 5,117	[snd_soc_dapm_out_drv] = 5,118	[snd_soc_dapm_sink] = 6,119	[snd_soc_dapm_pga] = 6,120	[snd_soc_dapm_buffer] = 6,121	[snd_soc_dapm_scheduler] = 6,122	[snd_soc_dapm_effect] = 6,123	[snd_soc_dapm_src] = 6,124	[snd_soc_dapm_asrc] = 6,125	[snd_soc_dapm_encoder] = 6,126	[snd_soc_dapm_decoder] = 6,127	[snd_soc_dapm_switch] = 7,128	[snd_soc_dapm_mixer_named_ctl] = 7,129	[snd_soc_dapm_mixer] = 7,130	[snd_soc_dapm_dac] = 8,131	[snd_soc_dapm_mic] = 9,132	[snd_soc_dapm_siggen] = 9,133	[snd_soc_dapm_input] = 9,134	[snd_soc_dapm_output] = 9,135	[snd_soc_dapm_micbias] = 10,136	[snd_soc_dapm_vmid] = 10,137	[snd_soc_dapm_mux] = 11,138	[snd_soc_dapm_demux] = 11,139	[snd_soc_dapm_aif_in] = 12,140	[snd_soc_dapm_aif_out] = 12,141	[snd_soc_dapm_dai_in] = 12,142	[snd_soc_dapm_dai_out] = 12,143	[snd_soc_dapm_dai_link] = 13,144	[snd_soc_dapm_supply] = 14,145	[snd_soc_dapm_clock_supply] = 15,146	[snd_soc_dapm_pinctrl] = 15,147	[snd_soc_dapm_regulator_supply] = 15,148	[snd_soc_dapm_post] = 16,149};150 151static void dapm_assert_locked(struct snd_soc_dapm_context *dapm)152{153	if (snd_soc_card_is_instantiated(dapm->card))154		snd_soc_dapm_mutex_assert_held(dapm);155}156 157static void pop_wait(u32 pop_time)158{159	if (pop_time)160		schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));161}162 163__printf(3, 4)164static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)165{166	va_list args;167	char *buf;168 169	if (!pop_time)170		return;171 172	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);173	if (buf == NULL)174		return;175 176	va_start(args, fmt);177	vsnprintf(buf, PAGE_SIZE, fmt, args);178	dev_info(dev, "%s", buf);179	va_end(args);180 181	kfree(buf);182}183 184static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)185{186	return !list_empty(&w->dirty);187}188 189static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)190{191	dapm_assert_locked(w->dapm);192 193	if (!dapm_dirty_widget(w)) {194		dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",195			 w->name, reason);196		list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);197	}198}199 200/*201 * Common implementation for dapm_widget_invalidate_input_paths() and202 * dapm_widget_invalidate_output_paths(). The function is inlined since the203 * combined size of the two specialized functions is only marginally larger then204 * the size of the generic function and at the same time the fast path of the205 * specialized functions is significantly smaller than the generic function.206 */207static __always_inline void dapm_widget_invalidate_paths(208	struct snd_soc_dapm_widget *w, enum snd_soc_dapm_direction dir)209{210	enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir);211	struct snd_soc_dapm_widget *node;212	struct snd_soc_dapm_path *p;213	LIST_HEAD(list);214 215	dapm_assert_locked(w->dapm);216 217	if (w->endpoints[dir] == -1)218		return;219 220	list_add_tail(&w->work_list, &list);221	w->endpoints[dir] = -1;222 223	list_for_each_entry(w, &list, work_list) {224		snd_soc_dapm_widget_for_each_path(w, dir, p) {225			if (p->is_supply || p->weak || !p->connect)226				continue;227			node = p->node[rdir];228			if (node->endpoints[dir] != -1) {229				node->endpoints[dir] = -1;230				list_add_tail(&node->work_list, &list);231			}232		}233	}234}235 236/*237 * dapm_widget_invalidate_input_paths() - Invalidate the cached number of238 *  input paths239 * @w: The widget for which to invalidate the cached number of input paths240 *241 * Resets the cached number of inputs for the specified widget and all widgets242 * that can be reached via outcoming paths from the widget.243 *244 * This function must be called if the number of output paths for a widget might245 * have changed. E.g. if the source state of a widget changes or a path is added246 * or activated with the widget as the sink.247 */248static void dapm_widget_invalidate_input_paths(struct snd_soc_dapm_widget *w)249{250	dapm_widget_invalidate_paths(w, SND_SOC_DAPM_DIR_IN);251}252 253/*254 * dapm_widget_invalidate_output_paths() - Invalidate the cached number of255 *  output paths256 * @w: The widget for which to invalidate the cached number of output paths257 *258 * Resets the cached number of outputs for the specified widget and all widgets259 * that can be reached via incoming paths from the widget.260 *261 * This function must be called if the number of output paths for a widget might262 * have changed. E.g. if the sink state of a widget changes or a path is added263 * or activated with the widget as the source.264 */265static void dapm_widget_invalidate_output_paths(struct snd_soc_dapm_widget *w)266{267	dapm_widget_invalidate_paths(w, SND_SOC_DAPM_DIR_OUT);268}269 270/*271 * dapm_path_invalidate() - Invalidates the cached number of inputs and outputs272 *  for the widgets connected to a path273 * @p: The path to invalidate274 *275 * Resets the cached number of inputs for the sink of the path and the cached276 * number of outputs for the source of the path.277 *278 * This function must be called when a path is added, removed or the connected279 * state changes.280 */281static void dapm_path_invalidate(struct snd_soc_dapm_path *p)282{283	/*284	 * Weak paths or supply paths do not influence the number of input or285	 * output paths of their neighbors.286	 */287	if (p->weak || p->is_supply)288		return;289 290	/*291	 * The number of connected endpoints is the sum of the number of292	 * connected endpoints of all neighbors. If a node with 0 connected293	 * endpoints is either connected or disconnected that sum won't change,294	 * so there is no need to re-check the path.295	 */296	if (p->source->endpoints[SND_SOC_DAPM_DIR_IN] != 0)297		dapm_widget_invalidate_input_paths(p->sink);298	if (p->sink->endpoints[SND_SOC_DAPM_DIR_OUT] != 0)299		dapm_widget_invalidate_output_paths(p->source);300}301 302void dapm_mark_endpoints_dirty(struct snd_soc_card *card)303{304	struct snd_soc_dapm_widget *w;305 306	snd_soc_dapm_mutex_lock_root(card);307 308	for_each_card_widgets(card, w) {309		if (w->is_ep) {310			dapm_mark_dirty(w, "Rechecking endpoints");311			if (w->is_ep & SND_SOC_DAPM_EP_SINK)312				dapm_widget_invalidate_output_paths(w);313			if (w->is_ep & SND_SOC_DAPM_EP_SOURCE)314				dapm_widget_invalidate_input_paths(w);315		}316	}317 318	snd_soc_dapm_mutex_unlock(card);319}320EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty);321 322/* create a new dapm widget */323static inline struct snd_soc_dapm_widget *dapm_cnew_widget(324	const struct snd_soc_dapm_widget *_widget,325	const char *prefix)326{327	struct snd_soc_dapm_widget *w __free(kfree) = kmemdup(_widget,328							      sizeof(*_widget),329							      GFP_KERNEL);330	if (!w)331		return NULL;332 333	if (prefix)334		w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, _widget->name);335	else336		w->name = kstrdup_const(_widget->name, GFP_KERNEL);337	if (!w->name)338		return NULL;339 340	if (_widget->sname) {341		w->sname = kstrdup_const(_widget->sname, GFP_KERNEL);342		if (!w->sname) {343			kfree_const(w->name);344			return NULL;345		}346	}347 348	return_ptr(w);349}350 351struct dapm_kcontrol_data {352	unsigned int value;353	struct snd_soc_dapm_widget *widget;354	struct list_head paths;355	struct snd_soc_dapm_widget_list *wlist;356};357 358static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,359	struct snd_kcontrol *kcontrol, const char *ctrl_name)360{361	struct dapm_kcontrol_data *data;362	struct soc_mixer_control *mc;363	struct soc_enum *e;364	const char *name;365	int ret;366 367	data = kzalloc(sizeof(*data), GFP_KERNEL);368	if (!data)369		return -ENOMEM;370 371	INIT_LIST_HEAD(&data->paths);372 373	switch (widget->id) {374	case snd_soc_dapm_switch:375	case snd_soc_dapm_mixer:376	case snd_soc_dapm_mixer_named_ctl:377		mc = (struct soc_mixer_control *)kcontrol->private_value;378 379		if (mc->autodisable) {380			struct snd_soc_dapm_widget template;381 382			if (snd_soc_volsw_is_stereo(mc))383				dev_warn(widget->dapm->dev,384					 "ASoC: Unsupported stereo autodisable control '%s'\n",385					 ctrl_name);386 387			name = kasprintf(GFP_KERNEL, "%s %s", ctrl_name,388					 "Autodisable");389			if (!name) {390				ret = -ENOMEM;391				goto err_data;392			}393 394			memset(&template, 0, sizeof(template));395			template.reg = mc->reg;396			template.mask = (1 << fls(mc->max)) - 1;397			template.shift = mc->shift;398			if (mc->invert)399				template.off_val = mc->max;400			else401				template.off_val = 0;402			template.on_val = template.off_val;403			template.id = snd_soc_dapm_kcontrol;404			template.name = name;405 406			data->value = template.on_val;407 408			data->widget =409				snd_soc_dapm_new_control_unlocked(widget->dapm,410				&template);411			kfree(name);412			if (IS_ERR(data->widget)) {413				ret = PTR_ERR(data->widget);414				goto err_data;415			}416		}417		break;418	case snd_soc_dapm_demux:419	case snd_soc_dapm_mux:420		e = (struct soc_enum *)kcontrol->private_value;421 422		if (e->autodisable) {423			struct snd_soc_dapm_widget template;424 425			name = kasprintf(GFP_KERNEL, "%s %s", ctrl_name,426					 "Autodisable");427			if (!name) {428				ret = -ENOMEM;429				goto err_data;430			}431 432			memset(&template, 0, sizeof(template));433			template.reg = e->reg;434			template.mask = e->mask;435			template.shift = e->shift_l;436			template.off_val = snd_soc_enum_item_to_val(e, 0);437			template.on_val = template.off_val;438			template.id = snd_soc_dapm_kcontrol;439			template.name = name;440 441			data->value = template.on_val;442 443			data->widget = snd_soc_dapm_new_control_unlocked(444						widget->dapm, &template);445			kfree(name);446			if (IS_ERR(data->widget)) {447				ret = PTR_ERR(data->widget);448				goto err_data;449			}450 451			snd_soc_dapm_add_path(widget->dapm, data->widget,452					      widget, NULL, NULL);453		} else if (e->reg != SND_SOC_NOPM) {454			data->value = soc_dapm_read(widget->dapm, e->reg) &455				      (e->mask << e->shift_l);456		}457		break;458	default:459		break;460	}461 462	kcontrol->private_data = data;463 464	return 0;465 466err_data:467	kfree(data);468	return ret;469}470 471static void dapm_kcontrol_free(struct snd_kcontrol *kctl)472{473	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);474 475	list_del(&data->paths);476	kfree(data->wlist);477	kfree(data);478}479 480static struct snd_soc_dapm_widget_list *dapm_kcontrol_get_wlist(481	const struct snd_kcontrol *kcontrol)482{483	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);484 485	return data->wlist;486}487 488static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol,489	struct snd_soc_dapm_widget *widget)490{491	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);492	struct snd_soc_dapm_widget_list *new_wlist;493	unsigned int n;494 495	if (data->wlist)496		n = data->wlist->num_widgets + 1;497	else498		n = 1;499 500	new_wlist = krealloc(data->wlist,501			     struct_size(new_wlist, widgets, n),502			     GFP_KERNEL);503	if (!new_wlist)504		return -ENOMEM;505 506	new_wlist->num_widgets = n;507	new_wlist->widgets[n - 1] = widget;508 509	data->wlist = new_wlist;510 511	return 0;512}513 514static void dapm_kcontrol_add_path(const struct snd_kcontrol *kcontrol,515	struct snd_soc_dapm_path *path)516{517	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);518 519	list_add_tail(&path->list_kcontrol, &data->paths);520}521 522static bool dapm_kcontrol_is_powered(const struct snd_kcontrol *kcontrol)523{524	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);525 526	if (!data->widget)527		return true;528 529	return data->widget->power;530}531 532static struct list_head *dapm_kcontrol_get_path_list(533	const struct snd_kcontrol *kcontrol)534{535	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);536 537	return &data->paths;538}539 540#define dapm_kcontrol_for_each_path(path, kcontrol) \541	list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \542		list_kcontrol)543 544unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)545{546	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);547 548	return data->value;549}550EXPORT_SYMBOL_GPL(dapm_kcontrol_get_value);551 552static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,553	unsigned int value)554{555	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);556 557	if (data->value == value)558		return false;559 560	if (data->widget) {561		switch (dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->id) {562		case snd_soc_dapm_switch:563		case snd_soc_dapm_mixer:564		case snd_soc_dapm_mixer_named_ctl:565			data->widget->on_val = value & data->widget->mask;566			break;567		case snd_soc_dapm_demux:568		case snd_soc_dapm_mux:569			data->widget->on_val = value >> data->widget->shift;570			break;571		default:572			data->widget->on_val = value;573			break;574		}575	}576 577	data->value = value;578 579	return true;580}581 582/**583 * snd_soc_dapm_kcontrol_widget() - Returns the widget associated to a584 *   kcontrol585 * @kcontrol: The kcontrol586 */587struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_widget(588				struct snd_kcontrol *kcontrol)589{590	return dapm_kcontrol_get_wlist(kcontrol)->widgets[0];591}592EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_widget);593 594/**595 * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a596 *  kcontrol597 * @kcontrol: The kcontrol598 *599 * Note: This function must only be used on kcontrols that are known to have600 * been registered for a CODEC. Otherwise the behaviour is undefined.601 */602struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(603	struct snd_kcontrol *kcontrol)604{605	return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm;606}607EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm);608 609static void dapm_reset(struct snd_soc_card *card)610{611	struct snd_soc_dapm_widget *w;612 613	snd_soc_dapm_mutex_assert_held(card);614 615	memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));616 617	for_each_card_widgets(card, w) {618		w->new_power = w->power;619		w->power_checked = false;620	}621}622 623static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm)624{625	if (!dapm->component)626		return NULL;627	return dapm->component->name_prefix;628}629 630static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg)631{632	if (!dapm->component)633		return -EIO;634	return  snd_soc_component_read(dapm->component, reg);635}636 637static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm,638	int reg, unsigned int mask, unsigned int value)639{640	if (!dapm->component)641		return -EIO;642	return snd_soc_component_update_bits(dapm->component, reg,643					     mask, value);644}645 646static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm,647	int reg, unsigned int mask, unsigned int value)648{649	if (!dapm->component)650		return -EIO;651	return snd_soc_component_test_bits(dapm->component, reg, mask, value);652}653 654static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)655{656	if (dapm->component)657		snd_soc_component_async_complete(dapm->component);658}659 660static struct snd_soc_dapm_widget *661dapm_wcache_lookup(struct snd_soc_dapm_widget *w, const char *name)662{663	if (w) {664		struct list_head *wlist = &w->dapm->card->widgets;665		const int depth = 2;666		int i = 0;667 668		list_for_each_entry_from(w, wlist, list) {669			if (!strcmp(name, w->name))670				return w;671 672			if (++i == depth)673				break;674		}675	}676 677	return NULL;678}679 680/**681 * snd_soc_dapm_force_bias_level() - Sets the DAPM bias level682 * @dapm: The DAPM context for which to set the level683 * @level: The level to set684 *685 * Forces the DAPM bias level to a specific state. It will call the bias level686 * callback of DAPM context with the specified level. This will even happen if687 * the context is already at the same level. Furthermore it will not go through688 * the normal bias level sequencing, meaning any intermediate states between the689 * current and the target state will not be entered.690 *691 * Note that the change in bias level is only temporary and the next time692 * snd_soc_dapm_sync() is called the state will be set to the level as693 * determined by the DAPM core. The function is mainly intended to be used to694 * used during probe or resume from suspend to power up the device so695 * initialization can be done, before the DAPM core takes over.696 */697int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm,698	enum snd_soc_bias_level level)699{700	int ret = 0;701 702	if (dapm->component)703		ret = snd_soc_component_set_bias_level(dapm->component, level);704 705	if (ret == 0)706		dapm->bias_level = level;707 708	return ret;709}710EXPORT_SYMBOL_GPL(snd_soc_dapm_force_bias_level);711 712/**713 * snd_soc_dapm_set_bias_level - set the bias level for the system714 * @dapm: DAPM context715 * @level: level to configure716 *717 * Configure the bias (power) levels for the SoC audio device.718 *719 * Returns 0 for success else error.720 */721static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,722				       enum snd_soc_bias_level level)723{724	struct snd_soc_card *card = dapm->card;725	int ret = 0;726 727	trace_snd_soc_bias_level_start(dapm, level);728 729	ret = snd_soc_card_set_bias_level(card, dapm, level);730	if (ret != 0)731		goto out;732 733	if (!card || dapm != &card->dapm)734		ret = snd_soc_dapm_force_bias_level(dapm, level);735 736	if (ret != 0)737		goto out;738 739	ret = snd_soc_card_set_bias_level_post(card, dapm, level);740out:741	trace_snd_soc_bias_level_done(dapm, level);742 743	return ret;744}745 746/* connect mux widget to its interconnecting audio paths */747static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,748	struct snd_soc_dapm_path *path, const char *control_name,749	struct snd_soc_dapm_widget *w)750{751	const struct snd_kcontrol_new *kcontrol = &w->kcontrol_news[0];752	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;753	unsigned int item;754	int i;755 756	if (e->reg != SND_SOC_NOPM) {757		unsigned int val;758		val = soc_dapm_read(dapm, e->reg);759		val = (val >> e->shift_l) & e->mask;760		item = snd_soc_enum_val_to_item(e, val);761	} else {762		/* since a virtual mux has no backing registers to763		 * decide which path to connect, it will try to match764		 * with the first enumeration.  This is to ensure765		 * that the default mux choice (the first) will be766		 * correctly powered up during initialization.767		 */768		item = 0;769	}770 771	i = match_string(e->texts, e->items, control_name);772	if (i < 0)773		return -ENODEV;774 775	path->name = e->texts[i];776	path->connect = (i == item);777	return 0;778 779}780 781/* set up initial codec paths */782static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i,783				       int nth_path)784{785	struct soc_mixer_control *mc = (struct soc_mixer_control *)786		p->sink->kcontrol_news[i].private_value;787	unsigned int reg = mc->reg;788	unsigned int invert = mc->invert;789 790	if (reg != SND_SOC_NOPM) {791		unsigned int shift = mc->shift;792		unsigned int max = mc->max;793		unsigned int mask = (1 << fls(max)) - 1;794		unsigned int val = soc_dapm_read(p->sink->dapm, reg);795 796		/*797		 * The nth_path argument allows this function to know798		 * which path of a kcontrol it is setting the initial799		 * status for. Ideally this would support any number800		 * of paths and channels. But since kcontrols only come801		 * in mono and stereo variants, we are limited to 2802		 * channels.803		 *804		 * The following code assumes for stereo controls the805		 * first path is the left channel, and all remaining806		 * paths are the right channel.807		 */808		if (snd_soc_volsw_is_stereo(mc) && nth_path > 0) {809			if (reg != mc->rreg)810				val = soc_dapm_read(p->sink->dapm, mc->rreg);811			val = (val >> mc->rshift) & mask;812		} else {813			val = (val >> shift) & mask;814		}815		if (invert)816			val = max - val;817		p->connect = !!val;818	} else {819		/* since a virtual mixer has no backing registers to820		 * decide which path to connect, it will try to match821		 * with initial state.  This is to ensure822		 * that the default mixer choice will be823		 * correctly powered up during initialization.824		 */825		p->connect = invert;826	}827}828 829/* connect mixer widget to its interconnecting audio paths */830static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,831	struct snd_soc_dapm_path *path, const char *control_name)832{833	int i, nth_path = 0;834 835	/* search for mixer kcontrol */836	for (i = 0; i < path->sink->num_kcontrols; i++) {837		if (!strcmp(control_name, path->sink->kcontrol_news[i].name)) {838			path->name = path->sink->kcontrol_news[i].name;839			dapm_set_mixer_path_status(path, i, nth_path++);840			return 0;841		}842	}843	return -ENODEV;844}845 846static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,847	struct snd_soc_dapm_widget *kcontrolw,848	const struct snd_kcontrol_new *kcontrol_new,849	struct snd_kcontrol **kcontrol)850{851	struct snd_soc_dapm_widget *w;852	int i;853 854	*kcontrol = NULL;855 856	for_each_card_widgets(dapm->card, w) {857		if (w == kcontrolw || w->dapm != kcontrolw->dapm)858			continue;859		for (i = 0; i < w->num_kcontrols; i++) {860			if (&w->kcontrol_news[i] == kcontrol_new) {861				if (w->kcontrols)862					*kcontrol = w->kcontrols[i];863				return 1;864			}865		}866	}867 868	return 0;869}870 871/*872 * Determine if a kcontrol is shared. If it is, look it up. If it isn't,873 * create it. Either way, add the widget into the control's widget list874 */875static int dapm_create_or_share_kcontrol(struct snd_soc_dapm_widget *w,876	int kci)877{878	struct snd_soc_dapm_context *dapm = w->dapm;879	struct snd_card *card = dapm->card->snd_card;880	const char *prefix;881	size_t prefix_len;882	int shared;883	struct snd_kcontrol *kcontrol;884	bool wname_in_long_name, kcname_in_long_name;885	char *long_name = NULL;886	const char *name;887	int ret = 0;888 889	prefix = soc_dapm_prefix(dapm);890	if (prefix)891		prefix_len = strlen(prefix) + 1;892	else893		prefix_len = 0;894 895	shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],896					 &kcontrol);897 898	if (!kcontrol) {899		if (shared) {900			wname_in_long_name = false;901			kcname_in_long_name = true;902		} else {903			switch (w->id) {904			case snd_soc_dapm_switch:905			case snd_soc_dapm_mixer:906			case snd_soc_dapm_pga:907			case snd_soc_dapm_effect:908			case snd_soc_dapm_out_drv:909				wname_in_long_name = true;910				kcname_in_long_name = true;911				break;912			case snd_soc_dapm_mixer_named_ctl:913				wname_in_long_name = false;914				kcname_in_long_name = true;915				break;916			case snd_soc_dapm_demux:917			case snd_soc_dapm_mux:918				wname_in_long_name = true;919				kcname_in_long_name = false;920				break;921			default:922				return -EINVAL;923			}924		}925		if (w->no_wname_in_kcontrol_name)926			wname_in_long_name = false;927 928		if (wname_in_long_name && kcname_in_long_name) {929			/*930			 * The control will get a prefix from the control931			 * creation process but we're also using the same932			 * prefix for widgets so cut the prefix off the933			 * front of the widget name.934			 */935			long_name = kasprintf(GFP_KERNEL, "%s %s",936				 w->name + prefix_len,937				 w->kcontrol_news[kci].name);938			if (long_name == NULL)939				return -ENOMEM;940 941			name = long_name;942		} else if (wname_in_long_name) {943			long_name = NULL;944			name = w->name + prefix_len;945		} else {946			long_name = NULL;947			name = w->kcontrol_news[kci].name;948		}949 950		kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name,951					prefix);952		if (!kcontrol) {953			ret = -ENOMEM;954			goto exit_free;955		}956 957		kcontrol->private_free = dapm_kcontrol_free;958 959		ret = dapm_kcontrol_data_alloc(w, kcontrol, name);960		if (ret) {961			snd_ctl_free_one(kcontrol);962			goto exit_free;963		}964 965		ret = snd_ctl_add(card, kcontrol);966		if (ret < 0) {967			dev_err(dapm->dev,968				"ASoC: failed to add widget %s dapm kcontrol %s: %d\n",969				w->name, name, ret);970			goto exit_free;971		}972	}973 974	ret = dapm_kcontrol_add_widget(kcontrol, w);975	if (ret == 0)976		w->kcontrols[kci] = kcontrol;977 978exit_free:979	kfree(long_name);980 981	return ret;982}983 984/* create new dapm mixer control */985static int dapm_new_mixer(struct snd_soc_dapm_widget *w)986{987	int i, ret;988	struct snd_soc_dapm_path *path;989	struct dapm_kcontrol_data *data;990 991	/* add kcontrol */992	for (i = 0; i < w->num_kcontrols; i++) {993		/* match name */994		snd_soc_dapm_widget_for_each_source_path(w, path) {995			/* mixer/mux paths name must match control name */996			if (path->name != (char *)w->kcontrol_news[i].name)997				continue;998 999			if (!w->kcontrols[i]) {1000				ret = dapm_create_or_share_kcontrol(w, i);1001				if (ret < 0)1002					return ret;1003			}1004 1005			dapm_kcontrol_add_path(w->kcontrols[i], path);1006 1007			data = snd_kcontrol_chip(w->kcontrols[i]);1008			if (data->widget)1009				snd_soc_dapm_add_path(data->widget->dapm,1010						      data->widget,1011						      path->source,1012						      NULL, NULL);1013		}1014	}1015 1016	return 0;1017}1018 1019/* create new dapm mux control */1020static int dapm_new_mux(struct snd_soc_dapm_widget *w)1021{1022	struct snd_soc_dapm_context *dapm = w->dapm;1023	enum snd_soc_dapm_direction dir;1024	struct snd_soc_dapm_path *path;1025	const char *type;1026	int ret;1027 1028	switch (w->id) {1029	case snd_soc_dapm_mux:1030		dir = SND_SOC_DAPM_DIR_OUT;1031		type = "mux";1032		break;1033	case snd_soc_dapm_demux:1034		dir = SND_SOC_DAPM_DIR_IN;1035		type = "demux";1036		break;1037	default:1038		return -EINVAL;1039	}1040 1041	if (w->num_kcontrols != 1) {1042		dev_err(dapm->dev,1043			"ASoC: %s %s has incorrect number of controls\n", type,1044			w->name);1045		return -EINVAL;1046	}1047 1048	if (list_empty(&w->edges[dir])) {1049		dev_err(dapm->dev, "ASoC: %s %s has no paths\n", type, w->name);1050		return -EINVAL;1051	}1052 1053	ret = dapm_create_or_share_kcontrol(w, 0);1054	if (ret < 0)1055		return ret;1056 1057	snd_soc_dapm_widget_for_each_path(w, dir, path) {1058		if (path->name)1059			dapm_kcontrol_add_path(w->kcontrols[0], path);1060	}1061 1062	return 0;1063}1064 1065/* create new dapm volume control */1066static int dapm_new_pga(struct snd_soc_dapm_widget *w)1067{1068	int i;1069 1070	for (i = 0; i < w->num_kcontrols; i++) {1071		int ret = dapm_create_or_share_kcontrol(w, i);1072		if (ret < 0)1073			return ret;1074	}1075 1076	return 0;1077}1078 1079/* create new dapm dai link control */1080static int dapm_new_dai_link(struct snd_soc_dapm_widget *w)1081{1082	int i;1083	struct snd_soc_pcm_runtime *rtd = w->priv;1084 1085	/* create control for links with > 1 config */1086	if (rtd->dai_link->num_c2c_params <= 1)1087		return 0;1088 1089	/* add kcontrol */1090	for (i = 0; i < w->num_kcontrols; i++) {1091		struct snd_soc_dapm_context *dapm = w->dapm;1092		struct snd_card *card = dapm->card->snd_card;1093		struct snd_kcontrol *kcontrol = snd_soc_cnew(&w->kcontrol_news[i],1094							     w, w->name, NULL);1095		int ret = snd_ctl_add(card, kcontrol);1096 1097		if (ret < 0) {1098			dev_err(dapm->dev,1099				"ASoC: failed to add widget %s dapm kcontrol %s: %d\n",1100				w->name, w->kcontrol_news[i].name, ret);1101			return ret;1102		}1103		kcontrol->private_data = w;1104		w->kcontrols[i] = kcontrol;1105	}1106 1107	return 0;1108}1109 1110/* We implement power down on suspend by checking the power state of1111 * the ALSA card - when we are suspending the ALSA state for the card1112 * is set to D3.1113 */1114static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)1115{1116	int level = snd_power_get_state(widget->dapm->card->snd_card);1117 1118	switch (level) {1119	case SNDRV_CTL_POWER_D3hot:1120	case SNDRV_CTL_POWER_D3cold:1121		if (widget->ignore_suspend)1122			dev_dbg(widget->dapm->dev, "ASoC: %s ignoring suspend\n",1123				widget->name);1124		return widget->ignore_suspend;1125	default:1126		return 1;1127	}1128}1129 1130static void dapm_widget_list_free(struct snd_soc_dapm_widget_list **list)1131{1132	kfree(*list);1133}1134 1135static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list,1136	struct list_head *widgets)1137{1138	struct snd_soc_dapm_widget *w;1139	struct list_head *it;1140	unsigned int size = 0;1141	unsigned int i = 0;1142 1143	list_for_each(it, widgets)1144		size++;1145 1146	*list = kzalloc(struct_size(*list, widgets, size), GFP_KERNEL);1147	if (*list == NULL)1148		return -ENOMEM;1149 1150	(*list)->num_widgets = size;1151 1152	list_for_each_entry(w, widgets, work_list)1153		(*list)->widgets[i++] = w;1154 1155	(*list)->num_widgets = i;1156 1157	return 0;1158}1159 1160/*1161 * Recursively reset the cached number of inputs or outputs for the specified1162 * widget and all widgets that can be reached via incoming or outcoming paths1163 * from the widget.1164 */1165static void invalidate_paths_ep(struct snd_soc_dapm_widget *widget,1166	enum snd_soc_dapm_direction dir)1167{1168	enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir);1169	struct snd_soc_dapm_path *path;1170 1171	widget->endpoints[dir] = -1;1172 1173	snd_soc_dapm_widget_for_each_path(widget, rdir, path) {1174		if (path->weak || path->is_supply)1175			continue;1176 1177		if (path->walking)1178			return;1179 1180		if (path->connect) {1181			path->walking = 1;1182			invalidate_paths_ep(path->node[dir], dir);1183			path->walking = 0;1184		}1185	}1186}1187 1188/*1189 * Common implementation for is_connected_output_ep() and1190 * is_connected_input_ep(). The function is inlined since the combined size of1191 * the two specialized functions is only marginally larger then the size of the1192 * generic function and at the same time the fast path of the specialized1193 * functions is significantly smaller than the generic function.1194 */1195static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget,1196	struct list_head *list, enum snd_soc_dapm_direction dir,1197	int (*fn)(struct snd_soc_dapm_widget *, struct list_head *,1198		  bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,1199						enum snd_soc_dapm_direction)),1200	bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,1201				      enum snd_soc_dapm_direction))1202{1203	enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir);1204	struct snd_soc_dapm_path *path;1205	int con = 0;1206 1207	if (widget->endpoints[dir] >= 0)1208		return widget->endpoints[dir];1209 1210	DAPM_UPDATE_STAT(widget, path_checks);1211 1212	/* do we need to add this widget to the list ? */1213	if (list)1214		list_add_tail(&widget->work_list, list);1215 1216	if (custom_stop_condition && custom_stop_condition(widget, dir)) {1217		list = NULL;1218		custom_stop_condition = NULL;1219	}1220 1221	if ((widget->is_ep & SND_SOC_DAPM_DIR_TO_EP(dir)) && widget->connected) {1222		widget->endpoints[dir] = snd_soc_dapm_suspend_check(widget);1223		return widget->endpoints[dir];1224	}1225 1226	snd_soc_dapm_widget_for_each_path(widget, rdir, path) {1227		DAPM_UPDATE_STAT(widget, neighbour_checks);1228 1229		if (path->weak || path->is_supply)1230			continue;1231 1232		if (path->walking)1233			return 1;1234 1235		trace_snd_soc_dapm_path(widget, dir, path);1236 1237		if (path->connect) {1238			path->walking = 1;1239			con += fn(path->node[dir], list, custom_stop_condition);1240			path->walking = 0;1241		}1242	}1243 1244	widget->endpoints[dir] = con;1245 1246	return con;1247}1248 1249/*1250 * Recursively check for a completed path to an active or physically connected1251 * output widget. Returns number of complete paths.1252 *1253 * Optionally, can be supplied with a function acting as a stopping condition.1254 * This function takes the dapm widget currently being examined and the walk1255 * direction as an arguments, it should return true if widgets from that point1256 * in the graph onwards should not be added to the widget list.1257 */1258static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,1259	struct list_head *list,1260	bool (*custom_stop_condition)(struct snd_soc_dapm_widget *i,1261				      enum snd_soc_dapm_direction))1262{1263	return is_connected_ep(widget, list, SND_SOC_DAPM_DIR_OUT,1264			is_connected_output_ep, custom_stop_condition);1265}1266 1267/*1268 * Recursively check for a completed path to an active or physically connected1269 * input widget. Returns number of complete paths.1270 *1271 * Optionally, can be supplied with a function acting as a stopping condition.1272 * This function takes the dapm widget currently being examined and the walk1273 * direction as an arguments, it should return true if the walk should be1274 * stopped and false otherwise.1275 */1276static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,1277	struct list_head *list,1278	bool (*custom_stop_condition)(struct snd_soc_dapm_widget *i,1279				      enum snd_soc_dapm_direction))1280{1281	return is_connected_ep(widget, list, SND_SOC_DAPM_DIR_IN,1282			is_connected_input_ep, custom_stop_condition);1283}1284 1285/**1286 * snd_soc_dapm_dai_get_connected_widgets - query audio path and it's widgets.1287 * @dai: the soc DAI.1288 * @stream: stream direction.1289 * @list: list of active widgets for this stream.1290 * @custom_stop_condition: (optional) a function meant to stop the widget graph1291 *                         walk based on custom logic.1292 *1293 * Queries DAPM graph as to whether a valid audio stream path exists for1294 * the initial stream specified by name. This takes into account1295 * current mixer and mux kcontrol settings. Creates list of valid widgets.1296 *1297 * Optionally, can be supplied with a function acting as a stopping condition.1298 * This function takes the dapm widget currently being examined and the walk1299 * direction as an arguments, it should return true if the walk should be1300 * stopped and false otherwise.1301 *1302 * Returns the number of valid paths or negative error.1303 */1304int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,1305	struct snd_soc_dapm_widget_list **list,1306	bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,1307				      enum snd_soc_dapm_direction))1308{1309	struct snd_soc_card *card = dai->component->card;1310	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, stream);1311	LIST_HEAD(widgets);1312	int paths;1313	int ret;1314 1315	snd_soc_dapm_mutex_lock(card);1316 1317	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {1318		invalidate_paths_ep(w, SND_SOC_DAPM_DIR_OUT);1319		paths = is_connected_output_ep(w, &widgets,1320				custom_stop_condition);1321	} else {1322		invalidate_paths_ep(w, SND_SOC_DAPM_DIR_IN);1323		paths = is_connected_input_ep(w, &widgets,1324				custom_stop_condition);1325	}1326 1327	/* Drop starting point */1328	list_del(widgets.next);1329 1330	ret = dapm_widget_list_create(list, &widgets);1331	if (ret)1332		paths = ret;1333 1334	trace_snd_soc_dapm_connected(paths, stream);1335	snd_soc_dapm_mutex_unlock(card);1336 1337	return paths;1338}1339EXPORT_SYMBOL_GPL(snd_soc_dapm_dai_get_connected_widgets);1340 1341void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list)1342{1343	dapm_widget_list_free(list);1344}1345EXPORT_SYMBOL_GPL(snd_soc_dapm_dai_free_widgets);1346 1347/*1348 * Handler for regulator supply widget.1349 */1350int dapm_regulator_event(struct snd_soc_dapm_widget *w,1351		   struct snd_kcontrol *kcontrol, int event)1352{1353	int ret;1354 1355	soc_dapm_async_complete(w->dapm);1356 1357	if (SND_SOC_DAPM_EVENT_ON(event)) {1358		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {1359			ret = regulator_allow_bypass(w->regulator, false);1360			if (ret != 0)1361				dev_warn(w->dapm->dev,1362					 "ASoC: Failed to unbypass %s: %d\n",1363					 w->name, ret);1364		}1365 1366		return regulator_enable(w->regulator);1367	} else {1368		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {1369			ret = regulator_allow_bypass(w->regulator, true);1370			if (ret != 0)1371				dev_warn(w->dapm->dev,1372					 "ASoC: Failed to bypass %s: %d\n",1373					 w->name, ret);1374		}1375 1376		return regulator_disable_deferred(w->regulator, w->shift);1377	}1378}1379EXPORT_SYMBOL_GPL(dapm_regulator_event);1380 1381/*1382 * Handler for pinctrl widget.1383 */1384int dapm_pinctrl_event(struct snd_soc_dapm_widget *w,1385		       struct snd_kcontrol *kcontrol, int event)1386{1387	struct snd_soc_dapm_pinctrl_priv *priv = w->priv;1388	struct pinctrl *p = w->pinctrl;1389	struct pinctrl_state *s;1390 1391	if (!p || !priv)1392		return -EIO;1393 1394	if (SND_SOC_DAPM_EVENT_ON(event))1395		s = pinctrl_lookup_state(p, priv->active_state);1396	else1397		s = pinctrl_lookup_state(p, priv->sleep_state);1398 1399	if (IS_ERR(s))1400		return PTR_ERR(s);1401 1402	return pinctrl_select_state(p, s);1403}1404EXPORT_SYMBOL_GPL(dapm_pinctrl_event);1405 1406/*1407 * Handler for clock supply widget.1408 */1409int dapm_clock_event(struct snd_soc_dapm_widget *w,1410		   struct snd_kcontrol *kcontrol, int event)1411{1412	if (!w->clk)1413		return -EIO;1414 1415	soc_dapm_async_complete(w->dapm);1416 1417	if (SND_SOC_DAPM_EVENT_ON(event)) {1418		return clk_prepare_enable(w->clk);1419	} else {1420		clk_disable_unprepare(w->clk);1421		return 0;1422	}1423 1424	return 0;1425}1426EXPORT_SYMBOL_GPL(dapm_clock_event);1427 1428static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)1429{1430	if (w->power_checked)1431		return w->new_power;1432 1433	if (w->force)1434		w->new_power = 1;1435	else1436		w->new_power = w->power_check(w);1437 1438	w->power_checked = true;1439 1440	return w->new_power;1441}1442 1443/* Generic check to see if a widget should be powered. */1444static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)1445{1446	int in, out;1447 1448	DAPM_UPDATE_STAT(w, power_checks);1449 1450	in = is_connected_input_ep(w, NULL, NULL);1451	out = is_connected_output_ep(w, NULL, NULL);1452	return out != 0 && in != 0;1453}1454 1455/* Check to see if a power supply is needed */1456static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)1457{1458	struct snd_soc_dapm_path *path;1459 1460	DAPM_UPDATE_STAT(w, power_checks);1461 1462	/* Check if one of our outputs is connected */1463	snd_soc_dapm_widget_for_each_sink_path(w, path) {1464		DAPM_UPDATE_STAT(w, neighbour_checks);1465 1466		if (path->weak)1467			continue;1468 1469		if (path->connected &&1470		    !path->connected(path->source, path->sink))1471			continue;1472 1473		if (dapm_widget_power_check(path->sink))1474			return 1;1475	}1476 1477	return 0;1478}1479 1480static int dapm_always_on_check_power(struct snd_soc_dapm_widget *w)1481{1482	return w->connected;1483}1484 1485static int dapm_seq_compare(struct snd_soc_dapm_widget *a,1486			    struct snd_soc_dapm_widget *b,1487			    bool power_up)1488{1489	int *sort;1490 1491	BUILD_BUG_ON(ARRAY_SIZE(dapm_up_seq) != SND_SOC_DAPM_TYPE_COUNT);1492	BUILD_BUG_ON(ARRAY_SIZE(dapm_down_seq) != SND_SOC_DAPM_TYPE_COUNT);1493 1494	if (power_up)1495		sort = dapm_up_seq;1496	else1497		sort = dapm_down_seq;1498 1499	WARN_ONCE(sort[a->id] == 0, "offset a->id %d not initialized\n", a->id);1500	WARN_ONCE(sort[b->id] == 0, "offset b->id %d not initialized\n", b->id);1501 1502	if (sort[a->id] != sort[b->id])1503		return sort[a->id] - sort[b->id];1504	if (a->subseq != b->subseq) {1505		if (power_up)1506			return a->subseq - b->subseq;1507		else1508			return b->subseq - a->subseq;1509	}1510	if (a->reg != b->reg)1511		return a->reg - b->reg;1512	if (a->dapm != b->dapm)1513		return (unsigned long)a->dapm - (unsigned long)b->dapm;1514 1515	return 0;1516}1517 1518/* Insert a widget in order into a DAPM power sequence. */1519static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,1520			    struct list_head *list,1521			    bool power_up)1522{1523	struct snd_soc_dapm_widget *w;1524 1525	list_for_each_entry(w, list, power_list)1526		if (dapm_seq_compare(new_widget, w, power_up) < 0) {1527			list_add_tail(&new_widget->power_list, &w->power_list);1528			return;1529		}1530 1531	list_add_tail(&new_widget->power_list, list);1532}1533 1534static void dapm_seq_check_event(struct snd_soc_card *card,1535				 struct snd_soc_dapm_widget *w, int event)1536{1537	const char *ev_name;1538	int power;1539 1540	switch (event) {1541	case SND_SOC_DAPM_PRE_PMU:1542		ev_name = "PRE_PMU";1543		power = 1;1544		break;1545	case SND_SOC_DAPM_POST_PMU:1546		ev_name = "POST_PMU";1547		power = 1;1548		break;1549	case SND_SOC_DAPM_PRE_PMD:1550		ev_name = "PRE_PMD";1551		power = 0;1552		break;1553	case SND_SOC_DAPM_POST_PMD:1554		ev_name = "POST_PMD";1555		power = 0;1556		break;1557	case SND_SOC_DAPM_WILL_PMU:1558		ev_name = "WILL_PMU";1559		power = 1;1560		break;1561	case SND_SOC_DAPM_WILL_PMD:1562		ev_name = "WILL_PMD";1563		power = 0;1564		break;1565	default:1566		WARN(1, "Unknown event %d\n", event);1567		return;1568	}1569 1570	if (w->new_power != power)1571		return;1572 1573	if (w->event && (w->event_flags & event)) {1574		int ret;1575 1576		pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",1577			w->name, ev_name);1578		soc_dapm_async_complete(w->dapm);1579		trace_snd_soc_dapm_widget_event_start(w, event);1580		ret = w->event(w, NULL, event);1581		trace_snd_soc_dapm_widget_event_done(w, event);1582		if (ret < 0)1583			dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n",1584			       ev_name, w->name, ret);1585	}1586}1587 1588/* Apply the coalesced changes from a DAPM sequence */1589static void dapm_seq_run_coalesced(struct snd_soc_card *card,1590				   struct list_head *pending)1591{1592	struct snd_soc_dapm_context *dapm;1593	struct snd_soc_dapm_widget *w;1594	int reg;1595	unsigned int value = 0;1596	unsigned int mask = 0;1597 1598	w = list_first_entry(pending, struct snd_soc_dapm_widget, power_list);1599	reg = w->reg;1600	dapm = w->dapm;1601 1602	list_for_each_entry(w, pending, power_list) {1603		WARN_ON(reg != w->reg || dapm != w->dapm);1604		w->power = w->new_power;1605 1606		mask |= w->mask << w->shift;1607		if (w->power)1608			value |= w->on_val << w->shift;1609		else1610			value |= w->off_val << w->shift;1611 1612		pop_dbg(dapm->dev, card->pop_time,1613			"pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",1614			w->name, reg, value, mask);1615 1616		/* Check for events */1617		dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMU);1618		dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMD);1619	}1620 1621	if (reg >= 0) {1622		/* Any widget will do, they should all be updating the1623		 * same register.1624		 */1625 1626		pop_dbg(dapm->dev, card->pop_time,1627			"pop test : Applying 0x%x/0x%x to %x in %dms\n",1628			value, mask, reg, card->pop_time);1629		pop_wait(card->pop_time);1630		soc_dapm_update_bits(dapm, reg, mask, value);1631	}1632 1633	list_for_each_entry(w, pending, power_list) {1634		dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMU);1635		dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMD);1636	}1637}1638 1639/* Apply a DAPM power sequence.1640 *1641 * We walk over a pre-sorted list of widgets to apply power to.  In1642 * order to minimise the number of writes to the device required1643 * multiple widgets will be updated in a single write where possible.1644 * Currently anything that requires more than a single write is not1645 * handled.1646 */1647static void dapm_seq_run(struct snd_soc_card *card,1648	struct list_head *list, int event, bool power_up)1649{1650	struct snd_soc_dapm_widget *w, *n;1651	struct snd_soc_dapm_context *d;1652	LIST_HEAD(pending);1653	int cur_sort = -1;1654	int cur_subseq = -1;1655	int cur_reg = SND_SOC_NOPM;1656	struct snd_soc_dapm_context *cur_dapm = NULL;1657	int i;1658	int *sort;1659 1660	if (power_up)1661		sort = dapm_up_seq;1662	else1663		sort = dapm_down_seq;1664 1665	list_for_each_entry_safe(w, n, list, power_list) {1666		int ret = 0;1667 1668		/* Do we need to apply any queued changes? */1669		if (sort[w->id] != cur_sort || w->reg != cur_reg ||1670		    w->dapm != cur_dapm || w->subseq != cur_subseq) {1671			if (!list_empty(&pending))1672				dapm_seq_run_coalesced(card, &pending);1673 1674			if (cur_dapm && cur_dapm->component) {1675				for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)1676					if (sort[i] == cur_sort)1677						snd_soc_component_seq_notifier(1678							cur_dapm->component,1679							i, cur_subseq);1680			}1681 1682			if (cur_dapm && w->dapm != cur_dapm)1683				soc_dapm_async_complete(cur_dapm);1684 1685			INIT_LIST_HEAD(&pending);1686			cur_sort = -1;1687			cur_subseq = INT_MIN;1688			cur_reg = SND_SOC_NOPM;1689			cur_dapm = NULL;1690		}1691 1692		switch (w->id) {1693		case snd_soc_dapm_pre:1694			if (!w->event)1695				continue;1696 1697			if (event == SND_SOC_DAPM_STREAM_START)1698				ret = w->event(w,1699					       NULL, SND_SOC_DAPM_PRE_PMU);1700			else if (event == SND_SOC_DAPM_STREAM_STOP)1701				ret = w->event(w,1702					       NULL, SND_SOC_DAPM_PRE_PMD);1703			break;1704 1705		case snd_soc_dapm_post:1706			if (!w->event)1707				continue;1708 1709			if (event == SND_SOC_DAPM_STREAM_START)1710				ret = w->event(w,1711					       NULL, SND_SOC_DAPM_POST_PMU);1712			else if (event == SND_SOC_DAPM_STREAM_STOP)1713				ret = w->event(w,1714					       NULL, SND_SOC_DAPM_POST_PMD);1715			break;1716 1717		default:1718			/* Queue it up for application */1719			cur_sort = sort[w->id];1720			cur_subseq = w->subseq;1721			cur_reg = w->reg;1722			cur_dapm = w->dapm;1723			list_move(&w->power_list, &pending);1724			break;1725		}1726 1727		if (ret < 0)1728			dev_err(w->dapm->dev,1729				"ASoC: Failed to apply widget power: %d\n", ret);1730	}1731 1732	if (!list_empty(&pending))1733		dapm_seq_run_coalesced(card, &pending);1734 1735	if (cur_dapm && cur_dapm->component) {1736		for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)1737			if (sort[i] == cur_sort)1738				snd_soc_component_seq_notifier(1739					cur_dapm->component,1740					i, cur_subseq);1741	}1742 1743	for_each_card_dapms(card, d)1744		soc_dapm_async_complete(d);1745}1746 1747static void dapm_widget_update(struct snd_soc_card *card)1748{1749	struct snd_soc_dapm_update *update = card->update;1750	struct snd_soc_dapm_widget_list *wlist;1751	struct snd_soc_dapm_widget *w = NULL;1752	unsigned int wi;1753	int ret;1754 1755	if (!update || !dapm_kcontrol_is_powered(update->kcontrol))1756		return;1757 1758	wlist = dapm_kcontrol_get_wlist(update->kcontrol);1759 1760	for_each_dapm_widgets(wlist, wi, w) {1761		if (w->event && (w->event_flags & SND_SOC_DAPM_PRE_REG)) {1762			ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);1763			if (ret != 0)1764				dev_err(w->dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",1765					   w->name, ret);1766		}1767	}1768 1769	if (!w)1770		return;1771 1772	ret = soc_dapm_update_bits(w->dapm, update->reg, update->mask,1773		update->val);1774	if (ret < 0)1775		dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",1776			w->name, ret);1777 1778	if (update->has_second_set) {1779		ret = soc_dapm_update_bits(w->dapm, update->reg2,1780					   update->mask2, update->val2);1781		if (ret < 0)1782			dev_err(w->dapm->dev,1783				"ASoC: %s DAPM update failed: %d\n",1784				w->name, ret);1785	}1786 1787	for_each_dapm_widgets(wlist, wi, w) {1788		if (w->event && (w->event_flags & SND_SOC_DAPM_POST_REG)) {1789			ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);1790			if (ret != 0)1791				dev_err(w->dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",1792					   w->name, ret);1793		}1794	}1795}1796 1797/* Async callback run prior to DAPM sequences - brings to _PREPARE if1798 * they're changing state.1799 */1800static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)1801{1802	struct snd_soc_dapm_context *d = data;1803	int ret;1804 1805	/* If we're off and we're not supposed to go into STANDBY */1806	if (d->bias_level == SND_SOC_BIAS_OFF &&1807	    d->target_bias_level != SND_SOC_BIAS_OFF) {1808		if (d->dev && cookie)1809			pm_runtime_get_sync(d->dev);1810 1811		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);1812		if (ret != 0)1813			dev_err(d->dev,1814				"ASoC: Failed to turn on bias: %d\n", ret);1815	}1816 1817	/* Prepare for a transition to ON or away from ON */1818	if ((d->target_bias_level == SND_SOC_BIAS_ON &&1819	     d->bias_level != SND_SOC_BIAS_ON) ||1820	    (d->target_bias_level != SND_SOC_BIAS_ON &&1821	     d->bias_level == SND_SOC_BIAS_ON)) {1822		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);1823		if (ret != 0)1824			dev_err(d->dev,1825				"ASoC: Failed to prepare bias: %d\n", ret);1826	}1827}1828 1829/* Async callback run prior to DAPM sequences - brings to their final1830 * state.1831 */1832static void dapm_post_sequence_async(void *data, async_cookie_t cookie)1833{1834	struct snd_soc_dapm_context *d = data;1835	int ret;1836 1837	/* If we just powered the last thing off drop to standby bias */1838	if (d->bias_level == SND_SOC_BIAS_PREPARE &&1839	    (d->target_bias_level == SND_SOC_BIAS_STANDBY ||1840	     d->target_bias_level == SND_SOC_BIAS_OFF)) {1841		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);1842		if (ret != 0)1843			dev_err(d->dev, "ASoC: Failed to apply standby bias: %d\n",1844				ret);1845	}1846 1847	/* If we're in standby and can support bias off then do that */1848	if (d->bias_level == SND_SOC_BIAS_STANDBY &&1849	    d->target_bias_level == SND_SOC_BIAS_OFF) {1850		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);1851		if (ret != 0)1852			dev_err(d->dev, "ASoC: Failed to turn off bias: %d\n",1853				ret);1854 1855		if (d->dev && cookie)1856			pm_runtime_put(d->dev);1857	}1858 1859	/* If we just powered up then move to active bias */1860	if (d->bias_level == SND_SOC_BIAS_PREPARE &&1861	    d->target_bias_level == SND_SOC_BIAS_ON) {1862		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON);1863		if (ret != 0)1864			dev_err(d->dev, "ASoC: Failed to apply active bias: %d\n",1865				ret);1866	}1867}1868 1869static void dapm_widget_set_peer_power(struct snd_soc_dapm_widget *peer,1870				       bool power, bool connect)1871{1872	/* If a connection is being made or broken then that update1873	 * will have marked the peer dirty, otherwise the widgets are1874	 * not connected and this update has no impact. */1875	if (!connect)1876		return;1877 1878	/* If the peer is already in the state we're moving to then we1879	 * won't have an impact on it. */1880	if (power != peer->power)1881		dapm_mark_dirty(peer, "peer state change");1882}1883 1884static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,1885				  struct list_head *up_list,1886				  struct list_head *down_list)1887{1888	struct snd_soc_dapm_path *path;1889	int power;1890 1891	switch (w->id) {1892	case snd_soc_dapm_pre:1893		power = 0;1894		goto end;1895	case snd_soc_dapm_post:1896		power = 1;1897		goto end;1898	default:1899		break;1900	}1901 1902	power = dapm_widget_power_check(w);1903 1904	if (w->power == power)1905		return;1906 1907	trace_snd_soc_dapm_widget_power(w, power);1908 1909	/*1910	 * If we changed our power state perhaps our neigbours1911	 * changed also.1912	 */1913	snd_soc_dapm_widget_for_each_source_path(w, path)1914		dapm_widget_set_peer_power(path->source, power, path->connect);1915 1916	/*1917	 * Supplies can't affect their outputs, only their inputs1918	 */1919	if (!w->is_supply)1920		snd_soc_dapm_widget_for_each_sink_path(w, path)1921			dapm_widget_set_peer_power(path->sink, power, path->connect);1922 1923end:1924	if (power)1925		dapm_seq_insert(w, up_list, true);1926	else1927		dapm_seq_insert(w, down_list, false);1928}1929 1930static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm)1931{1932	if (dapm->idle_bias_off)1933		return true;1934 1935	switch (snd_power_get_state(dapm->card->snd_card)) {1936	case SNDRV_CTL_POWER_D3hot:1937	case SNDRV_CTL_POWER_D3cold:1938		return dapm->suspend_bias_off;1939	default:1940		break;1941	}1942 1943	return false;1944}1945 1946/*1947 * Scan each dapm widget for complete audio path.1948 * A complete path is a route that has valid endpoints i.e.:-1949 *1950 *  o DAC to output pin.1951 *  o Input pin to ADC.1952 *  o Input pin to Output pin (bypass, sidetone)1953 *  o DAC to ADC (loopback).1954 */1955static int dapm_power_widgets(struct snd_soc_card *card, int event)1956{1957	struct snd_soc_dapm_widget *w;1958	struct snd_soc_dapm_context *d;1959	LIST_HEAD(up_list);1960	LIST_HEAD(down_list);1961	ASYNC_DOMAIN_EXCLUSIVE(async_domain);1962	enum snd_soc_bias_level bias;1963	int ret;1964 1965	snd_soc_dapm_mutex_assert_held(card);1966 1967	trace_snd_soc_dapm_start(card, event);1968 1969	for_each_card_dapms(card, d) {1970		if (dapm_idle_bias_off(d))1971			d->target_bias_level = SND_SOC_BIAS_OFF;1972		else1973			d->target_bias_level = SND_SOC_BIAS_STANDBY;1974	}1975 1976	dapm_reset(card);1977 1978	/* Check which widgets we need to power and store them in1979	 * lists indicating if they should be powered up or down.  We1980	 * only check widgets that have been flagged as dirty but note1981	 * that new widgets may be added to the dirty list while we1982	 * iterate.1983	 */1984	list_for_each_entry(w, &card->dapm_dirty, dirty) {1985		dapm_power_one_widget(w, &up_list, &down_list);1986	}1987 1988	for_each_card_widgets(card, w) {1989		switch (w->id) {1990		case snd_soc_dapm_pre:1991		case snd_soc_dapm_post:1992			/* These widgets always need to be powered */1993			break;1994		default:1995			list_del_init(&w->dirty);1996			break;1997		}1998 1999		if (w->new_power) {2000			d = w->dapm;2001 2002			/* Supplies and micbiases only bring the2003			 * context up to STANDBY as unless something2004			 * else is active and passing audio they2005			 * generally don't require full power.  Signal2006			 * generators are virtual pins and have no2007			 * power impact themselves.2008			 */2009			switch (w->id) {2010			case snd_soc_dapm_siggen:2011			case snd_soc_dapm_vmid:2012				break;2013			case snd_soc_dapm_supply:2014			case snd_soc_dapm_regulator_supply:2015			case snd_soc_dapm_pinctrl:2016			case snd_soc_dapm_clock_supply:2017			case snd_soc_dapm_micbias:2018				if (d->target_bias_level < SND_SOC_BIAS_STANDBY)2019					d->target_bias_level = SND_SOC_BIAS_STANDBY;2020				break;2021			default:2022				d->target_bias_level = SND_SOC_BIAS_ON;2023				break;2024			}2025		}2026 2027	}2028 2029	/* Force all contexts in the card to the same bias state if2030	 * they're not ground referenced.2031	 */2032	bias = SND_SOC_BIAS_OFF;2033	for_each_card_dapms(card, d)2034		if (d->target_bias_level > bias)2035			bias = d->target_bias_level;2036	for_each_card_dapms(card, d)2037		if (!dapm_idle_bias_off(d))2038			d->target_bias_level = bias;2039 2040	trace_snd_soc_dapm_walk_done(card);2041 2042	/* Run card bias changes at first */2043	dapm_pre_sequence_async(&card->dapm, 0);2044	/* Run other bias changes in parallel */2045	for_each_card_dapms(card, d) {2046		if (d != &card->dapm && d->bias_level != d->target_bias_level)2047			async_schedule_domain(dapm_pre_sequence_async, d,2048						&async_domain);2049	}2050	async_synchronize_full_domain(&async_domain);2051 2052	list_for_each_entry(w, &down_list, power_list) {2053		dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMD);2054	}2055 2056	list_for_each_entry(w, &up_list, power_list) {2057		dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMU);2058	}2059 2060	/* Power down widgets first; try to avoid amplifying pops. */2061	dapm_seq_run(card, &down_list, event, false);2062 2063	dapm_widget_update(card);2064 2065	/* Now power up. */2066	dapm_seq_run(card, &up_list, event, true);2067 2068	/* Run all the bias changes in parallel */2069	for_each_card_dapms(card, d) {2070		if (d != &card->dapm && d->bias_level != d->target_bias_level)2071			async_schedule_domain(dapm_post_sequence_async, d,2072						&async_domain);2073	}2074	async_synchronize_full_domain(&async_domain);2075	/* Run card bias changes at last */2076	dapm_post_sequence_async(&card->dapm, 0);2077 2078	/* do we need to notify any clients that DAPM event is complete */2079	for_each_card_dapms(card, d) {2080		if (!d->component)2081			continue;2082 2083		ret = snd_soc_component_stream_event(d->component, event);2084		if (ret < 0)2085			return ret;2086	}2087 2088	pop_dbg(card->dev, card->pop_time,2089		"DAPM sequencing finished, waiting %dms\n", card->pop_time);2090	pop_wait(card->pop_time);2091 2092	trace_snd_soc_dapm_done(card, event);2093 2094	return 0;2095}2096 2097#ifdef CONFIG_DEBUG_FS2098 2099static const char * const snd_soc_dapm_type_name[] = {2100	[snd_soc_dapm_input]            = "input",2101	[snd_soc_dapm_output]           = "output",2102	[snd_soc_dapm_mux]              = "mux",2103	[snd_soc_dapm_demux]            = "demux",2104	[snd_soc_dapm_mixer]            = "mixer",2105	[snd_soc_dapm_mixer_named_ctl]  = "mixer_named_ctl",2106	[snd_soc_dapm_pga]              = "pga",2107	[snd_soc_dapm_out_drv]          = "out_drv",2108	[snd_soc_dapm_adc]              = "adc",2109	[snd_soc_dapm_dac]              = "dac",2110	[snd_soc_dapm_micbias]          = "micbias",2111	[snd_soc_dapm_mic]              = "mic",2112	[snd_soc_dapm_hp]               = "hp",2113	[snd_soc_dapm_spk]              = "spk",2114	[snd_soc_dapm_line]             = "line",2115	[snd_soc_dapm_switch]           = "switch",2116	[snd_soc_dapm_vmid]             = "vmid",2117	[snd_soc_dapm_pre]              = "pre",2118	[snd_soc_dapm_post]             = "post",2119	[snd_soc_dapm_supply]           = "supply",2120	[snd_soc_dapm_pinctrl]          = "pinctrl",2121	[snd_soc_dapm_regulator_supply] = "regulator_supply",2122	[snd_soc_dapm_clock_supply]     = "clock_supply",2123	[snd_soc_dapm_aif_in]           = "aif_in",2124	[snd_soc_dapm_aif_out]          = "aif_out",2125	[snd_soc_dapm_siggen]           = "siggen",2126	[snd_soc_dapm_sink]             = "sink",2127	[snd_soc_dapm_dai_in]           = "dai_in",2128	[snd_soc_dapm_dai_out]          = "dai_out",2129	[snd_soc_dapm_dai_link]         = "dai_link",2130	[snd_soc_dapm_kcontrol]         = "kcontrol",2131	[snd_soc_dapm_buffer]           = "buffer",2132	[snd_soc_dapm_scheduler]        = "scheduler",2133	[snd_soc_dapm_effect]           = "effect",2134	[snd_soc_dapm_src]              = "src",2135	[snd_soc_dapm_asrc]             = "asrc",2136	[snd_soc_dapm_encoder]          = "encoder",2137	[snd_soc_dapm_decoder]          = "decoder",2138};2139 2140static ssize_t dapm_widget_power_read_file(struct file *file,2141					   char __user *user_buf,2142					   size_t count, loff_t *ppos)2143{2144	struct snd_soc_dapm_widget *w = file->private_data;2145	enum snd_soc_dapm_direction dir, rdir;2146	char *buf;2147	int in, out;2148	ssize_t ret;2149	struct snd_soc_dapm_path *p = NULL;2150	const char *c_name;2151 2152	BUILD_BUG_ON(ARRAY_SIZE(snd_soc_dapm_type_name) != SND_SOC_DAPM_TYPE_COUNT);2153 2154	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);2155	if (!buf)2156		return -ENOMEM;2157 2158	snd_soc_dapm_mutex_lock_root(w->dapm);2159 2160	/* Supply widgets are not handled by is_connected_{input,output}_ep() */2161	if (w->is_supply) {2162		in = 0;2163		out = 0;2164	} else {2165		in = is_connected_input_ep(w, NULL, NULL);2166		out = is_connected_output_ep(w, NULL, NULL);2167	}2168 2169	ret = scnprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",2170		       w->name, w->power ? "On" : "Off",2171		       w->force ? " (forced)" : "", in, out);2172 2173	if (w->reg >= 0)2174		ret += scnprintf(buf + ret, PAGE_SIZE - ret,2175				" - R%d(0x%x) mask 0x%x",2176				w->reg, w->reg, w->mask << w->shift);2177 2178	ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");2179 2180	if (w->sname)2181		ret += scnprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",2182				w->sname,2183				w->active ? "active" : "inactive");2184 2185	ret += scnprintf(buf + ret, PAGE_SIZE - ret, " widget-type %s\n",2186			 snd_soc_dapm_type_name[w->id]);2187 2188	snd_soc_dapm_for_each_direction(dir) {2189		rdir = SND_SOC_DAPM_DIR_REVERSE(dir);2190		snd_soc_dapm_widget_for_each_path(w, dir, p) {2191			if (p->connected && !p->connected(p->source, p->sink))2192				continue;2193 2194			if (!p->connect)2195				continue;2196 2197			c_name = p->node[rdir]->dapm->component ?2198				p->node[rdir]->dapm->component->name : NULL;2199			ret += scnprintf(buf + ret, PAGE_SIZE - ret,2200					" %s  \"%s\" \"%s\" \"%s\"\n",2201					(rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out",2202					p->name ? p->name : "static",2203					p->node[rdir]->name, c_name);2204		}2205	}2206 2207	snd_soc_dapm_mutex_unlock(w->dapm);2208 2209	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);2210 2211	kfree(buf);2212	return ret;2213}2214 2215static const struct file_operations dapm_widget_power_fops = {2216	.open = simple_open,2217	.read = dapm_widget_power_read_file,2218	.llseek = default_llseek,2219};2220 2221static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,2222				   size_t count, loff_t *ppos)2223{2224	struct snd_soc_dapm_context *dapm = file->private_data;2225	char *level;2226 2227	switch (dapm->bias_level) {2228	case SND_SOC_BIAS_ON:2229		level = "On\n";2230		break;2231	case SND_SOC_BIAS_PREPARE:2232		level = "Prepare\n";2233		break;2234	case SND_SOC_BIAS_STANDBY:2235		level = "Standby\n";2236		break;2237	case SND_SOC_BIAS_OFF:2238		level = "Off\n";2239		break;2240	default:2241		WARN(1, "Unknown bias_level %d\n", dapm->bias_level);2242		level = "Unknown\n";2243		break;2244	}2245 2246	return simple_read_from_buffer(user_buf, count, ppos, level,2247				       strlen(level));2248}2249 2250static const struct file_operations dapm_bias_fops = {2251	.open = simple_open,2252	.read = dapm_bias_read_file,2253	.llseek = default_llseek,2254};2255 2256void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,2257	struct dentry *parent)2258{2259	if (IS_ERR_OR_NULL(parent))2260		return;2261 2262	dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);2263 2264	debugfs_create_file("bias_level", 0444, dapm->debugfs_dapm, dapm,2265			    &dapm_bias_fops);2266}2267 2268static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)2269{2270	struct snd_soc_dapm_context *dapm = w->dapm;2271 2272	if (!dapm->debugfs_dapm || !w->name)2273		return;2274 2275	debugfs_create_file(w->name, 0444, dapm->debugfs_dapm, w,2276			    &dapm_widget_power_fops);2277}2278 2279static void dapm_debugfs_free_widget(struct snd_soc_dapm_widget *w)2280{2281	struct snd_soc_dapm_context *dapm = w->dapm;2282 2283	if (!dapm->debugfs_dapm || !w->name)2284		return;2285 2286	debugfs_lookup_and_remove(w->name, dapm->debugfs_dapm);2287}2288 2289static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)2290{2291	debugfs_remove_recursive(dapm->debugfs_dapm);2292	dapm->debugfs_dapm = NULL;2293}2294 2295#else2296void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,2297	struct dentry *parent)2298{2299}2300 2301static inline void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)2302{2303}2304 2305static inline void dapm_debugfs_free_widget(struct snd_soc_dapm_widget *w)2306{2307}2308 2309static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)2310{2311}2312 2313#endif2314 2315/*2316 * soc_dapm_connect_path() - Connects or disconnects a path2317 * @path: The path to update2318 * @connect: The new connect state of the path. True if the path is connected,2319 *  false if it is disconnected.2320 * @reason: The reason why the path changed (for debugging only)2321 */2322static void soc_dapm_connect_path(struct snd_soc_dapm_path *path,2323	bool connect, const char *reason)2324{2325	if (path->connect == connect)2326		return;2327 2328	path->connect = connect;2329	dapm_mark_dirty(path->source, reason);2330	dapm_mark_dirty(path->sink, reason);2331	dapm_path_invalidate(path);2332}2333 2334/* test and update the power status of a mux widget */2335static int soc_dapm_mux_update_power(struct snd_soc_card *card,2336				 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)2337{2338	struct snd_soc_dapm_path *path;2339	int found = 0;2340	bool connect;2341 2342	snd_soc_dapm_mutex_assert_held(card);2343 2344	/* find dapm widget path assoc with kcontrol */2345	dapm_kcontrol_for_each_path(path, kcontrol) {2346		found = 1;2347		/* we now need to match the string in the enum to the path */2348		if (e && !(strcmp(path->name, e->texts[mux])))2349			connect = true;2350		else2351			connect = false;2352 2353		soc_dapm_connect_path(path, connect, "mux update");2354	}2355 2356	if (found)2357		dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);2358 2359	return found;2360}2361 2362int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,2363	struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,2364	struct snd_soc_dapm_update *update)2365{2366	struct snd_soc_card *card = dapm->card;2367	int ret;2368 2369	snd_soc_dapm_mutex_lock(card);2370	card->update = update;2371	ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);2372	card->update = NULL;2373	snd_soc_dapm_mutex_unlock(card);2374	if (ret > 0)2375		snd_soc_dpcm_runtime_update(card);2376	return ret;2377}2378EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);2379 2380/* test and update the power status of a mixer or switch widget */2381static int soc_dapm_mixer_update_power(struct snd_soc_card *card,2382				       struct snd_kcontrol *kcontrol,2383				       int connect, int rconnect)2384{2385	struct snd_soc_dapm_path *path;2386	int found = 0;2387 2388	snd_soc_dapm_mutex_assert_held(card);2389 2390	/* find dapm widget path assoc with kcontrol */2391	dapm_kcontrol_for_each_path(path, kcontrol) {2392		/*2393		 * Ideally this function should support any number of2394		 * paths and channels. But since kcontrols only come2395		 * in mono and stereo variants, we are limited to 22396		 * channels.2397		 *2398		 * The following code assumes for stereo controls the2399		 * first path (when 'found == 0') is the left channel,2400		 * and all remaining paths (when 'found == 1') are the2401		 * right channel.2402		 *2403		 * A stereo control is signified by a valid 'rconnect'2404		 * value, either 0 for unconnected, or >= 0 for connected.2405		 * This is chosen instead of using snd_soc_volsw_is_stereo,2406		 * so that the behavior of snd_soc_dapm_mixer_update_power2407		 * doesn't change even when the kcontrol passed in is2408		 * stereo.2409		 *2410		 * It passes 'connect' as the path connect status for2411		 * the left channel, and 'rconnect' for the right2412		 * channel.2413		 */2414		if (found && rconnect >= 0)2415			soc_dapm_connect_path(path, rconnect, "mixer update");2416		else2417			soc_dapm_connect_path(path, connect, "mixer update");2418		found = 1;2419	}2420 2421	if (found)2422		dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);2423 2424	return found;2425}2426 2427int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,2428	struct snd_kcontrol *kcontrol, int connect,2429	struct snd_soc_dapm_update *update)2430{2431	struct snd_soc_card *card = dapm->card;2432	int ret;2433 2434	snd_soc_dapm_mutex_lock(card);2435	card->update = update;2436	ret = soc_dapm_mixer_update_power(card, kcontrol, connect, -1);2437	card->update = NULL;2438	snd_soc_dapm_mutex_unlock(card);2439	if (ret > 0)2440		snd_soc_dpcm_runtime_update(card);2441	return ret;2442}2443EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);2444 2445static ssize_t dapm_widget_show_component(struct snd_soc_component *cmpnt,2446					  char *buf, int count)2447{2448	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);2449	struct snd_soc_dapm_widget *w;2450	char *state = "not set";2451 2452	/* card won't be set for the dummy component, as a spot fix2453	 * we're checking for that case specifically here but in future2454	 * we will ensure that the dummy component looks like others.2455	 */2456	if (!cmpnt->card)2457		return 0;2458 2459	for_each_card_widgets(cmpnt->card, w) {2460		if (w->dapm != dapm)2461			continue;2462 2463		/* only display widgets that burn power */2464		switch (w->id) {2465		case snd_soc_dapm_hp:2466		case snd_soc_dapm_mic:2467		case snd_soc_dapm_spk:2468		case snd_soc_dapm_line:2469		case snd_soc_dapm_micbias:2470		case snd_soc_dapm_dac:2471		case snd_soc_dapm_adc:2472		case snd_soc_dapm_pga:2473		case snd_soc_dapm_effect:2474		case snd_soc_dapm_out_drv:2475		case snd_soc_dapm_mixer:2476		case snd_soc_dapm_mixer_named_ctl:2477		case snd_soc_dapm_supply:2478		case snd_soc_dapm_regulator_supply:2479		case snd_soc_dapm_pinctrl:2480		case snd_soc_dapm_clock_supply:2481			if (w->name)2482				count += sysfs_emit_at(buf, count, "%s: %s\n",2483					w->name, w->power ? "On":"Off");2484		break;2485		default:2486		break;2487		}2488	}2489 2490	switch (snd_soc_dapm_get_bias_level(dapm)) {2491	case SND_SOC_BIAS_ON:2492		state = "On";2493		break;2494	case SND_SOC_BIAS_PREPARE:2495		state = "Prepare";2496		break;2497	case SND_SOC_BIAS_STANDBY:2498		state = "Standby";2499		break;2500	case SND_SOC_BIAS_OFF:2501		state = "Off";2502		break;2503	}2504	count += sysfs_emit_at(buf, count, "PM State: %s\n", state);2505 2506	return count;2507}2508 2509/* show dapm widget status in sys fs */2510static ssize_t dapm_widget_show(struct device *dev,2511	struct device_attribute *attr, char *buf)2512{2513	struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);2514	struct snd_soc_dai *codec_dai;2515	int i, count = 0;2516 2517	snd_soc_dapm_mutex_lock_root(rtd->card);2518 2519	for_each_rtd_codec_dais(rtd, i, codec_dai) {2520		struct snd_soc_component *cmpnt = codec_dai->component;2521 2522		count = dapm_widget_show_component(cmpnt, buf, count);2523	}2524 2525	snd_soc_dapm_mutex_unlock(rtd->card);2526 2527	return count;2528}2529 2530static DEVICE_ATTR_RO(dapm_widget);2531 2532struct attribute *soc_dapm_dev_attrs[] = {2533	&dev_attr_dapm_widget.attr,2534	NULL2535};2536 2537static void dapm_free_path(struct snd_soc_dapm_path *path)2538{2539	list_del(&path->list_node[SND_SOC_DAPM_DIR_IN]);2540	list_del(&path->list_node[SND_SOC_DAPM_DIR_OUT]);2541	list_del(&path->list_kcontrol);2542	list_del(&path->list);2543	kfree(path);2544}2545 2546/**2547 * snd_soc_dapm_free_widget - Free specified widget2548 * @w: widget to free2549 *2550 * Removes widget from all paths and frees memory occupied by it.2551 */2552void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w)2553{2554	struct snd_soc_dapm_path *p, *next_p;2555	enum snd_soc_dapm_direction dir;2556 2557	if (!w)2558		return;2559 2560	list_del(&w->list);2561	list_del(&w->dirty);2562	/*2563	 * remove source and sink paths associated to this widget.2564	 * While removing the path, remove reference to it from both2565	 * source and sink widgets so that path is removed only once.2566	 */2567	snd_soc_dapm_for_each_direction(dir) {2568		snd_soc_dapm_widget_for_each_path_safe(w, dir, p, next_p)2569			dapm_free_path(p);2570	}2571 2572	dapm_debugfs_free_widget(w);2573 2574	kfree(w->kcontrols);2575	kfree_const(w->name);2576	kfree_const(w->sname);2577	kfree(w);2578}2579EXPORT_SYMBOL_GPL(snd_soc_dapm_free_widget);2580 2581/* free all dapm widgets and resources */2582static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)2583{2584	struct snd_soc_dapm_widget *w, *next_w;2585 2586	for_each_card_widgets_safe(dapm->card, w, next_w) {2587		if (w->dapm != dapm)2588			continue;2589		snd_soc_dapm_free_widget(w);2590	}2591 2592	dapm->wcache_sink	= NULL;2593	dapm->wcache_source	= NULL;2594}2595 2596static struct snd_soc_dapm_widget *dapm_find_widget(2597			struct snd_soc_dapm_context *dapm, const char *pin,2598			bool search_other_contexts)2599{2600	struct snd_soc_dapm_widget *w;2601	struct snd_soc_dapm_widget *fallback = NULL;2602	char prefixed_pin[80];2603	const char *pin_name;2604	const char *prefix = soc_dapm_prefix(dapm);2605 2606	if (prefix) {2607		snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",2608			 prefix, pin);2609		pin_name = prefixed_pin;2610	} else {2611		pin_name = pin;2612	}2613 2614	for_each_card_widgets(dapm->card, w) {2615		if (!strcmp(w->name, pin_name)) {2616			if (w->dapm == dapm)2617				return w;2618			else2619				fallback = w;2620		}2621	}2622 2623	if (search_other_contexts)2624		return fallback;2625 2626	return NULL;2627}2628 2629/*2630 * set the DAPM pin status:2631 * returns 1 when the value has been updated, 0 when unchanged, or a negative2632 * error code; called from kcontrol put callback2633 */2634static int __snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,2635				  const char *pin, int status)2636{2637	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);2638	int ret = 0;2639 2640	dapm_assert_locked(dapm);2641 2642	if (!w) {2643		dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin);2644		return -EINVAL;2645	}2646 2647	if (w->connected != status) {2648		dapm_mark_dirty(w, "pin configuration");2649		dapm_widget_invalidate_input_paths(w);2650		dapm_widget_invalidate_output_paths(w);2651		ret = 1;2652	}2653 2654	w->connected = status;2655	if (status == 0)2656		w->force = 0;2657 2658	return ret;2659}2660 2661/*2662 * similar as __snd_soc_dapm_set_pin(), but returns 0 when successful;2663 * called from several API functions below2664 */2665static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,2666				const char *pin, int status)2667{2668	int ret = __snd_soc_dapm_set_pin(dapm, pin, status);2669 2670	return ret < 0 ? ret : 0;2671}2672 2673/**2674 * snd_soc_dapm_sync_unlocked - scan and power dapm paths2675 * @dapm: DAPM context2676 *2677 * Walks all dapm audio paths and powers widgets according to their2678 * stream or path usage.2679 *2680 * Requires external locking.2681 *2682 * Returns 0 for success.2683 */2684int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm)2685{2686	/*2687	 * Suppress early reports (eg, jacks syncing their state) to avoid2688	 * silly DAPM runs during card startup.2689	 */2690	if (!snd_soc_card_is_instantiated(dapm->card))2691		return 0;2692 2693	return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP);2694}2695EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked);2696 2697/**2698 * snd_soc_dapm_sync - scan and power dapm paths2699 * @dapm: DAPM context2700 *2701 * Walks all dapm audio paths and powers widgets according to their2702 * stream or path usage.2703 *2704 * Returns 0 for success.2705 */2706int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)2707{2708	int ret;2709 2710	snd_soc_dapm_mutex_lock(dapm);2711	ret = snd_soc_dapm_sync_unlocked(dapm);2712	snd_soc_dapm_mutex_unlock(dapm);2713	return ret;2714}2715EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);2716 2717static int dapm_update_dai_chan(struct snd_soc_dapm_path *p,2718				struct snd_soc_dapm_widget *w,2719				int channels)2720{2721	switch (w->id) {2722	case snd_soc_dapm_aif_out:2723	case snd_soc_dapm_aif_in:2724		break;2725	default:2726		return 0;2727	}2728 2729	dev_dbg(w->dapm->dev, "%s DAI route %s -> %s\n",2730		w->channel < channels ? "Connecting" : "Disconnecting",2731		p->source->name, p->sink->name);2732 2733	if (w->channel < channels)2734		soc_dapm_connect_path(p, true, "dai update");2735	else2736		soc_dapm_connect_path(p, false, "dai update");2737 2738	return 0;2739}2740 2741static int dapm_update_dai_unlocked(struct snd_pcm_substream *substream,2742				    struct snd_pcm_hw_params *params,2743				    struct snd_soc_dai *dai)2744{2745	int dir = substream->stream;2746	int channels = params_channels(params);2747	struct snd_soc_dapm_path *p;2748	struct snd_soc_dapm_widget *w;2749	int ret;2750 2751	w = snd_soc_dai_get_widget(dai, dir);2752 2753	if (!w)2754		return 0;2755 2756	dev_dbg(dai->dev, "Update DAI routes for %s %s\n", dai->name, snd_pcm_direction_name(dir));2757 2758	snd_soc_dapm_widget_for_each_sink_path(w, p) {2759		ret = dapm_update_dai_chan(p, p->sink, channels);2760		if (ret < 0)2761			return ret;2762	}2763 2764	snd_soc_dapm_widget_for_each_source_path(w, p) {2765		ret = dapm_update_dai_chan(p, p->source, channels);2766		if (ret < 0)2767			return ret;2768	}2769 2770	return 0;2771}2772 2773int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream,2774			    struct snd_pcm_hw_params *params,2775			    struct snd_soc_dai *dai)2776{2777	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);2778	int ret;2779 2780	snd_soc_dapm_mutex_lock(rtd->card);2781	ret = dapm_update_dai_unlocked(substream, params, dai);2782	snd_soc_dapm_mutex_unlock(rtd->card);2783 2784	return ret;2785}2786EXPORT_SYMBOL_GPL(snd_soc_dapm_update_dai);2787 2788int snd_soc_dapm_widget_name_cmp(struct snd_soc_dapm_widget *widget, const char *s)2789{2790	struct snd_soc_component *component = widget->dapm->component;2791	const char *wname = widget->name;2792 2793	if (component && component->name_prefix)2794		wname += strlen(component->name_prefix) + 1; /* plus space */2795 2796	return strcmp(wname, s);2797}2798EXPORT_SYMBOL_GPL(snd_soc_dapm_widget_name_cmp);2799 2800/*2801 * dapm_update_widget_flags() - Re-compute widget sink and source flags2802 * @w: The widget for which to update the flags2803 *2804 * Some widgets have a dynamic category which depends on which neighbors they2805 * are connected to. This function update the category for these widgets.2806 *2807 * This function must be called whenever a path is added or removed to a widget.2808 */2809static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w)2810{2811	enum snd_soc_dapm_direction dir;2812	struct snd_soc_dapm_path *p;2813	unsigned int ep;2814 2815	switch (w->id) {2816	case snd_soc_dapm_input:2817		/* On a fully routed card an input is never a source */2818		if (w->dapm->card->fully_routed)2819			return;2820		ep = SND_SOC_DAPM_EP_SOURCE;2821		snd_soc_dapm_widget_for_each_source_path(w, p) {2822			if (p->source->id == snd_soc_dapm_micbias ||2823				p->source->id == snd_soc_dapm_mic ||2824				p->source->id == snd_soc_dapm_line ||2825				p->source->id == snd_soc_dapm_output) {2826					ep = 0;2827					break;2828			}2829		}2830		break;2831	case snd_soc_dapm_output:2832		/* On a fully routed card a output is never a sink */2833		if (w->dapm->card->fully_routed)2834			return;2835		ep = SND_SOC_DAPM_EP_SINK;2836		snd_soc_dapm_widget_for_each_sink_path(w, p) {2837			if (p->sink->id == snd_soc_dapm_spk ||2838				p->sink->id == snd_soc_dapm_hp ||2839				p->sink->id == snd_soc_dapm_line ||2840				p->sink->id == snd_soc_dapm_input) {2841					ep = 0;2842					break;2843			}2844		}2845		break;2846	case snd_soc_dapm_line:2847		ep = 0;2848		snd_soc_dapm_for_each_direction(dir) {2849			if (!list_empty(&w->edges[dir]))2850				ep |= SND_SOC_DAPM_DIR_TO_EP(dir);2851		}2852		break;2853	default:2854		return;2855	}2856 2857	w->is_ep = ep;2858}2859 2860static int snd_soc_dapm_check_dynamic_path(struct snd_soc_dapm_context *dapm,2861	struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink,2862	const char *control)2863{2864	bool dynamic_source = false;2865	bool dynamic_sink = false;2866 2867	if (!control)2868		return 0;2869 2870	switch (source->id) {2871	case snd_soc_dapm_demux:2872		dynamic_source = true;2873		break;2874	default:2875		break;2876	}2877 2878	switch (sink->id) {2879	case snd_soc_dapm_mux:2880	case snd_soc_dapm_switch:2881	case snd_soc_dapm_mixer:2882	case snd_soc_dapm_mixer_named_ctl:2883		dynamic_sink = true;2884		break;2885	default:2886		break;2887	}2888 2889	if (dynamic_source && dynamic_sink) {2890		dev_err(dapm->dev,2891			"Direct connection between demux and mixer/mux not supported for path %s -> [%s] -> %s\n",2892			source->name, control, sink->name);2893		return -EINVAL;2894	} else if (!dynamic_source && !dynamic_sink) {2895		dev_err(dapm->dev,2896			"Control not supported for path %s -> [%s] -> %s\n",2897			source->name, control, sink->name);2898		return -EINVAL;2899	}2900 2901	return 0;2902}2903 2904static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,2905	struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,2906	const char *control,2907	int (*connected)(struct snd_soc_dapm_widget *source,2908			 struct snd_soc_dapm_widget *sink))2909{2910	enum snd_soc_dapm_direction dir;2911	struct snd_soc_dapm_path *path;2912	int ret;2913 2914	if (wsink->is_supply && !wsource->is_supply) {2915		dev_err(dapm->dev,2916			"Connecting non-supply widget to supply widget is not supported (%s -> %s)\n",2917			wsource->name, wsink->name);2918		return -EINVAL;2919	}2920 2921	if (connected && !wsource->is_supply) {2922		dev_err(dapm->dev,2923			"connected() callback only supported for supply widgets (%s -> %s)\n",2924			wsource->name, wsink->name);2925		return -EINVAL;2926	}2927 2928	if (wsource->is_supply && control) {2929		dev_err(dapm->dev,2930			"Conditional paths are not supported for supply widgets (%s -> [%s] -> %s)\n",2931			wsource->name, control, wsink->name);2932		return -EINVAL;2933	}2934 2935	ret = snd_soc_dapm_check_dynamic_path(dapm, wsource, wsink, control);2936	if (ret)2937		return ret;2938 2939	path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);2940	if (!path)2941		return -ENOMEM;2942 2943	path->node[SND_SOC_DAPM_DIR_IN] = wsource;2944	path->node[SND_SOC_DAPM_DIR_OUT] = wsink;2945 2946	path->connected = connected;2947	INIT_LIST_HEAD(&path->list);2948	INIT_LIST_HEAD(&path->list_kcontrol);2949 2950	if (wsource->is_supply || wsink->is_supply)2951		path->is_supply = 1;2952 2953	/* connect static paths */2954	if (control == NULL) {2955		path->connect = 1;2956	} else {2957		switch (wsource->id) {2958		case snd_soc_dapm_demux:2959			ret = dapm_connect_mux(dapm, path, control, wsource);2960			if (ret)2961				goto err;2962			break;2963		default:2964			break;2965		}2966 2967		switch (wsink->id) {2968		case snd_soc_dapm_mux:2969			ret = dapm_connect_mux(dapm, path, control, wsink);2970			if (ret != 0)2971				goto err;2972			break;2973		case snd_soc_dapm_switch:2974		case snd_soc_dapm_mixer:2975		case snd_soc_dapm_mixer_named_ctl:2976			ret = dapm_connect_mixer(dapm, path, control);2977			if (ret != 0)2978				goto err;2979			break;2980		default:2981			break;2982		}2983	}2984 2985	list_add(&path->list, &dapm->card->paths);2986 2987	snd_soc_dapm_for_each_direction(dir)2988		list_add(&path->list_node[dir], &path->node[dir]->edges[dir]);2989 2990	snd_soc_dapm_for_each_direction(dir) {2991		dapm_update_widget_flags(path->node[dir]);2992		dapm_mark_dirty(path->node[dir], "Route added");2993	}2994 2995	if (snd_soc_card_is_instantiated(dapm->card) && path->connect)2996		dapm_path_invalidate(path);2997 2998	return 0;2999err:3000	kfree(path);3001	return ret;3002}3003 3004static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,3005				  const struct snd_soc_dapm_route *route)3006{3007	struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;3008	struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;3009	const char *sink;3010	const char *source;3011	char prefixed_sink[80];3012	char prefixed_source[80];3013	const char *prefix;3014	unsigned int sink_ref = 0;3015	unsigned int source_ref = 0;3016	int ret;3017 3018	prefix = soc_dapm_prefix(dapm);3019	if (prefix) {3020		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",3021			 prefix, route->sink);3022		sink = prefixed_sink;3023		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",3024			 prefix, route->source);3025		source = prefixed_source;3026	} else {3027		sink = route->sink;3028		source = route->source;3029	}3030 3031	wsource	= dapm_wcache_lookup(dapm->wcache_source, source);3032	wsink	= dapm_wcache_lookup(dapm->wcache_sink,   sink);3033 3034	if (wsink && wsource)3035		goto skip_search;3036 3037	/*3038	 * find src and dest widgets over all widgets but favor a widget from3039	 * current DAPM context3040	 */3041	for_each_card_widgets(dapm->card, w) {3042		if (!wsink && !(strcmp(w->name, sink))) {3043			wtsink = w;3044			if (w->dapm == dapm) {3045				wsink = w;3046				if (wsource)3047					break;3048			}3049			sink_ref++;3050			if (sink_ref > 1)3051				dev_warn(dapm->dev,3052					"ASoC: sink widget %s overwritten\n",3053					w->name);3054			continue;3055		}3056		if (!wsource && !(strcmp(w->name, source))) {3057			wtsource = w;3058			if (w->dapm == dapm) {3059				wsource = w;3060				if (wsink)3061					break;3062			}3063			source_ref++;3064			if (source_ref > 1)3065				dev_warn(dapm->dev,3066					"ASoC: source widget %s overwritten\n",3067					w->name);3068		}3069	}3070	/* use widget from another DAPM context if not found from this */3071	if (!wsink)3072		wsink = wtsink;3073	if (!wsource)3074		wsource = wtsource;3075 3076	ret = -ENODEV;3077	if (!wsource)3078		goto err;3079	if (!wsink)3080		goto err;3081 3082skip_search:3083	/* update cache */3084	dapm->wcache_sink	= wsink;3085	dapm->wcache_source	= wsource;3086 3087	ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control,3088		route->connected);3089err:3090	if (ret)3091		dev_err(dapm->dev, "ASoC: Failed to add route %s%s -%s%s%s> %s%s\n",3092			source, !wsource ? "(*)" : "",3093			!route->control ? "" : "> [",3094			!route->control ? "" : route->control,3095			!route->control ? "" : "] -",3096			sink,  !wsink ? "(*)" : "");3097	return ret;3098}3099 3100static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,3101				  const struct snd_soc_dapm_route *route)3102{3103	struct snd_soc_dapm_path *path, *p;3104	const char *sink;3105	const char *source;3106	char prefixed_sink[80];3107	char prefixed_source[80];3108	const char *prefix;3109 3110	if (route->control) {3111		dev_err(dapm->dev,3112			"ASoC: Removal of routes with controls not supported\n");3113		return -EINVAL;3114	}3115 3116	prefix = soc_dapm_prefix(dapm);3117	if (prefix) {3118		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",3119			 prefix, route->sink);3120		sink = prefixed_sink;3121		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",3122			 prefix, route->source);3123		source = prefixed_source;3124	} else {3125		sink = route->sink;3126		source = route->source;3127	}3128 3129	path = NULL;3130	list_for_each_entry(p, &dapm->card->paths, list) {3131		if (strcmp(p->source->name, source) != 0)3132			continue;3133		if (strcmp(p->sink->name, sink) != 0)3134			continue;3135		path = p;3136		break;3137	}3138 3139	if (path) {3140		struct snd_soc_dapm_widget *wsource = path->source;3141		struct snd_soc_dapm_widget *wsink = path->sink;3142 3143		dapm_mark_dirty(wsource, "Route removed");3144		dapm_mark_dirty(wsink, "Route removed");3145		if (path->connect)3146			dapm_path_invalidate(path);3147 3148		dapm_free_path(path);3149 3150		/* Update any path related flags */3151		dapm_update_widget_flags(wsource);3152		dapm_update_widget_flags(wsink);3153	} else {3154		dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n",3155			 source, sink);3156	}3157 3158	return 0;3159}3160 3161/**3162 * snd_soc_dapm_add_routes - Add routes between DAPM widgets3163 * @dapm: DAPM context3164 * @route: audio routes3165 * @num: number of routes3166 *3167 * Connects 2 dapm widgets together via a named audio path. The sink is3168 * the widget receiving the audio signal, whilst the source is the sender3169 * of the audio signal.3170 *3171 * Returns 0 for success else error. On error all resources can be freed3172 * with a call to snd_soc_card_free().3173 */3174int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,3175			    const struct snd_soc_dapm_route *route, int num)3176{3177	int i, ret = 0;3178 3179	snd_soc_dapm_mutex_lock(dapm);3180	for (i = 0; i < num; i++) {3181		int r = snd_soc_dapm_add_route(dapm, route);3182		if (r < 0)3183			ret = r;3184		route++;3185	}3186	snd_soc_dapm_mutex_unlock(dapm);3187 3188	return ret;3189}3190EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);3191 3192/**3193 * snd_soc_dapm_del_routes - Remove routes between DAPM widgets3194 * @dapm: DAPM context3195 * @route: audio routes3196 * @num: number of routes3197 *3198 * Removes routes from the DAPM context.3199 */3200int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,3201			    const struct snd_soc_dapm_route *route, int num)3202{3203	int i;3204 3205	snd_soc_dapm_mutex_lock(dapm);3206	for (i = 0; i < num; i++) {3207		snd_soc_dapm_del_route(dapm, route);3208		route++;3209	}3210	snd_soc_dapm_mutex_unlock(dapm);3211 3212	return 0;3213}3214EXPORT_SYMBOL_GPL(snd_soc_dapm_del_routes);3215 3216static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,3217				   const struct snd_soc_dapm_route *route)3218{3219	struct snd_soc_dapm_widget *source = dapm_find_widget(dapm,3220							      route->source,3221							      true);3222	struct snd_soc_dapm_widget *sink = dapm_find_widget(dapm,3223							    route->sink,3224							    true);3225	struct snd_soc_dapm_path *path;3226	int count = 0;3227 3228	if (!source) {3229		dev_err(dapm->dev, "ASoC: Unable to find source %s for weak route\n",3230			route->source);3231		return -ENODEV;3232	}3233 3234	if (!sink) {3235		dev_err(dapm->dev, "ASoC: Unable to find sink %s for weak route\n",3236			route->sink);3237		return -ENODEV;3238	}3239 3240	if (route->control || route->connected)3241		dev_warn(dapm->dev, "ASoC: Ignoring control for weak route %s->%s\n",3242			 route->source, route->sink);3243 3244	snd_soc_dapm_widget_for_each_sink_path(source, path) {3245		if (path->sink == sink) {3246			path->weak = 1;3247			count++;3248		}3249	}3250 3251	if (count == 0)3252		dev_err(dapm->dev, "ASoC: No path found for weak route %s->%s\n",3253			route->source, route->sink);3254	if (count > 1)3255		dev_warn(dapm->dev, "ASoC: %d paths found for weak route %s->%s\n",3256			 count, route->source, route->sink);3257 3258	return 0;3259}3260 3261/**3262 * snd_soc_dapm_weak_routes - Mark routes between DAPM widgets as weak3263 * @dapm: DAPM context3264 * @route: audio routes3265 * @num: number of routes3266 *3267 * Mark existing routes matching those specified in the passed array3268 * as being weak, meaning that they are ignored for the purpose of3269 * power decisions.  The main intended use case is for sidetone paths3270 * which couple audio between other independent paths if they are both3271 * active in order to make the combination work better at the user3272 * level but which aren't intended to be "used".3273 *3274 * Note that CODEC drivers should not use this as sidetone type paths3275 * can frequently also be used as bypass paths.3276 */3277int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,3278			     const struct snd_soc_dapm_route *route, int num)3279{3280	int i;3281	int ret = 0;3282 3283	snd_soc_dapm_mutex_lock_root(dapm);3284	for (i = 0; i < num; i++) {3285		int err = snd_soc_dapm_weak_route(dapm, route);3286		if (err)3287			ret = err;3288		route++;3289	}3290	snd_soc_dapm_mutex_unlock(dapm);3291 3292	return ret;3293}3294EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);3295 3296/**3297 * snd_soc_dapm_new_widgets - add new dapm widgets3298 * @card: card to be checked for new dapm widgets3299 *3300 * Checks the codec for any new dapm widgets and creates them if found.3301 *3302 * Returns 0 for success.3303 */3304int snd_soc_dapm_new_widgets(struct snd_soc_card *card)3305{3306	struct snd_soc_dapm_widget *w;3307	unsigned int val;3308 3309	snd_soc_dapm_mutex_lock_root(card);3310 3311	for_each_card_widgets(card, w)3312	{3313		if (w->new)3314			continue;3315 3316		if (w->num_kcontrols) {3317			w->kcontrols = kcalloc(w->num_kcontrols,3318						sizeof(struct snd_kcontrol *),3319						GFP_KERNEL);3320			if (!w->kcontrols) {3321				snd_soc_dapm_mutex_unlock(card);3322				return -ENOMEM;3323			}3324		}3325 3326		switch(w->id) {3327		case snd_soc_dapm_switch:3328		case snd_soc_dapm_mixer:3329		case snd_soc_dapm_mixer_named_ctl:3330			dapm_new_mixer(w);3331			break;3332		case snd_soc_dapm_mux:3333		case snd_soc_dapm_demux:3334			dapm_new_mux(w);3335			break;3336		case snd_soc_dapm_pga:3337		case snd_soc_dapm_effect:3338		case snd_soc_dapm_out_drv:3339			dapm_new_pga(w);3340			break;3341		case snd_soc_dapm_dai_link:3342			dapm_new_dai_link(w);3343			break;3344		default:3345			break;3346		}3347 3348		/* Read the initial power state from the device */3349		if (w->reg >= 0) {3350			val = soc_dapm_read(w->dapm, w->reg);3351			val = val >> w->shift;3352			val &= w->mask;3353			if (val == w->on_val)3354				w->power = 1;3355		}3356 3357		w->new = 1;3358 3359		dapm_mark_dirty(w, "new widget");3360		dapm_debugfs_add_widget(w);3361	}3362 3363	dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);3364	snd_soc_dapm_mutex_unlock(card);3365	return 0;3366}3367EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);3368 3369/**3370 * snd_soc_dapm_get_volsw - dapm mixer get callback3371 * @kcontrol: mixer control3372 * @ucontrol: control element information3373 *3374 * Callback to get the value of a dapm mixer control.3375 *3376 * Returns 0 for success.3377 */3378int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,3379	struct snd_ctl_elem_value *ucontrol)3380{3381	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);3382	struct soc_mixer_control *mc =3383		(struct soc_mixer_control *)kcontrol->private_value;3384	int reg = mc->reg;3385	unsigned int shift = mc->shift;3386	int max = mc->max;3387	unsigned int width = fls(max);3388	unsigned int mask = (1 << fls(max)) - 1;3389	unsigned int invert = mc->invert;3390	unsigned int reg_val, val, rval = 0;3391 3392	snd_soc_dapm_mutex_lock(dapm);3393	if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) {3394		reg_val = soc_dapm_read(dapm, reg);3395		val = (reg_val >> shift) & mask;3396 3397		if (reg != mc->rreg)3398			reg_val = soc_dapm_read(dapm, mc->rreg);3399 3400		if (snd_soc_volsw_is_stereo(mc))3401			rval = (reg_val >> mc->rshift) & mask;3402	} else {3403		reg_val = dapm_kcontrol_get_value(kcontrol);3404		val = reg_val & mask;3405 3406		if (snd_soc_volsw_is_stereo(mc))3407			rval = (reg_val >> width) & mask;3408	}3409	snd_soc_dapm_mutex_unlock(dapm);3410 3411	if (invert)3412		ucontrol->value.integer.value[0] = max - val;3413	else3414		ucontrol->value.integer.value[0] = val;3415 3416	if (snd_soc_volsw_is_stereo(mc)) {3417		if (invert)3418			ucontrol->value.integer.value[1] = max - rval;3419		else3420			ucontrol->value.integer.value[1] = rval;3421	}3422 3423	return 0;3424}3425EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);3426 3427/**3428 * snd_soc_dapm_put_volsw - dapm mixer set callback3429 * @kcontrol: mixer control3430 * @ucontrol: control element information3431 *3432 * Callback to set the value of a dapm mixer control.3433 *3434 * Returns 0 for success.3435 */3436int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,3437	struct snd_ctl_elem_value *ucontrol)3438{3439	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);3440	struct snd_soc_card *card = dapm->card;3441	struct soc_mixer_control *mc =3442		(struct soc_mixer_control *)kcontrol->private_value;3443	int reg = mc->reg;3444	unsigned int shift = mc->shift;3445	int max = mc->max;3446	unsigned int width = fls(max);3447	unsigned int mask = (1 << width) - 1;3448	unsigned int invert = mc->invert;3449	unsigned int val, rval = 0;3450	int connect, rconnect = -1, change, reg_change = 0;3451	struct snd_soc_dapm_update update = {};3452	int ret = 0;3453 3454	val = (ucontrol->value.integer.value[0] & mask);3455	connect = !!val;3456 3457	if (invert)3458		val = max - val;3459 3460	if (snd_soc_volsw_is_stereo(mc)) {3461		rval = (ucontrol->value.integer.value[1] & mask);3462		rconnect = !!rval;3463		if (invert)3464			rval = max - rval;3465	}3466 3467	snd_soc_dapm_mutex_lock(card);3468 3469	/* This assumes field width < (bits in unsigned int / 2) */3470	if (width > sizeof(unsigned int) * 8 / 2)3471		dev_warn(dapm->dev,3472			 "ASoC: control %s field width limit exceeded\n",3473			 kcontrol->id.name);3474	change = dapm_kcontrol_set_value(kcontrol, val | (rval << width));3475 3476	if (reg != SND_SOC_NOPM) {3477		val = val << shift;3478		rval = rval << mc->rshift;3479 3480		reg_change = soc_dapm_test_bits(dapm, reg, mask << shift, val);3481 3482		if (snd_soc_volsw_is_stereo(mc))3483			reg_change |= soc_dapm_test_bits(dapm, mc->rreg,3484							 mask << mc->rshift,3485							 rval);3486	}3487 3488	if (change || reg_change) {3489		if (reg_change) {3490			if (snd_soc_volsw_is_stereo(mc)) {3491				update.has_second_set = true;3492				update.reg2 = mc->rreg;3493				update.mask2 = mask << mc->rshift;3494				update.val2 = rval;3495			}3496			update.kcontrol = kcontrol;3497			update.reg = reg;3498			update.mask = mask << shift;3499			update.val = val;3500			card->update = &update;3501		}3502 3503		ret = soc_dapm_mixer_update_power(card, kcontrol, connect,3504						  rconnect);3505 3506		card->update = NULL;3507	}3508 3509	snd_soc_dapm_mutex_unlock(card);3510 3511	if (ret > 0)3512		snd_soc_dpcm_runtime_update(card);3513 3514	return change;3515}3516EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);3517 3518/**3519 * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback3520 * @kcontrol: mixer control3521 * @ucontrol: control element information3522 *3523 * Callback to get the value of a dapm enumerated double mixer control.3524 *3525 * Returns 0 for success.3526 */3527int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,3528	struct snd_ctl_elem_value *ucontrol)3529{3530	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);3531	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;3532	unsigned int reg_val, val;3533 3534	snd_soc_dapm_mutex_lock(dapm);3535	if (e->reg != SND_SOC_NOPM && dapm_kcontrol_is_powered(kcontrol)) {3536		reg_val = soc_dapm_read(dapm, e->reg);3537	} else {3538		reg_val = dapm_kcontrol_get_value(kcontrol);3539	}3540	snd_soc_dapm_mutex_unlock(dapm);3541 3542	val = (reg_val >> e->shift_l) & e->mask;3543	ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val);3544	if (e->shift_l != e->shift_r) {3545		val = (reg_val >> e->shift_r) & e->mask;3546		val = snd_soc_enum_val_to_item(e, val);3547		ucontrol->value.enumerated.item[1] = val;3548	}3549 3550	return 0;3551}3552EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);3553 3554/**3555 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback3556 * @kcontrol: mixer control3557 * @ucontrol: control element information3558 *3559 * Callback to set the value of a dapm enumerated double mixer control.3560 *3561 * Returns 0 for success.3562 */3563int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,3564	struct snd_ctl_elem_value *ucontrol)3565{3566	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);3567	struct snd_soc_card *card = dapm->card;3568	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;3569	unsigned int *item = ucontrol->value.enumerated.item;3570	unsigned int val, change, reg_change = 0;3571	unsigned int mask;3572	struct snd_soc_dapm_update update = {};3573	int ret = 0;3574 3575	if (item[0] >= e->items)3576		return -EINVAL;3577 3578	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;3579	mask = e->mask << e->shift_l;3580	if (e->shift_l != e->shift_r) {3581		if (item[1] > e->items)3582			return -EINVAL;3583		val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;3584		mask |= e->mask << e->shift_r;3585	}3586 3587	snd_soc_dapm_mutex_lock(card);3588 3589	change = dapm_kcontrol_set_value(kcontrol, val);3590 3591	if (e->reg != SND_SOC_NOPM)3592		reg_change = soc_dapm_test_bits(dapm, e->reg, mask, val);3593 3594	if (change || reg_change) {3595		if (reg_change) {3596			update.kcontrol = kcontrol;3597			update.reg = e->reg;3598			update.mask = mask;3599			update.val = val;3600			card->update = &update;3601		}3602 3603		ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e);3604 3605		card->update = NULL;3606	}3607 3608	snd_soc_dapm_mutex_unlock(card);3609 3610	if (ret > 0)3611		snd_soc_dpcm_runtime_update(card);3612 3613	return change;3614}3615EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);3616 3617/**3618 * snd_soc_dapm_info_pin_switch - Info for a pin switch3619 *3620 * @kcontrol: mixer control3621 * @uinfo: control element information3622 *3623 * Callback to provide information about a pin switch control.3624 */3625int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,3626				 struct snd_ctl_elem_info *uinfo)3627{3628	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;3629	uinfo->count = 1;3630	uinfo->value.integer.min = 0;3631	uinfo->value.integer.max = 1;3632 3633	return 0;3634}3635EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);3636 3637/**3638 * snd_soc_dapm_get_pin_switch - Get information for a pin switch3639 *3640 * @kcontrol: mixer control3641 * @ucontrol: Value3642 */3643int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,3644				struct snd_ctl_elem_value *ucontrol)3645{3646	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);3647	const char *pin = (const char *)kcontrol->private_value;3648 3649	snd_soc_dapm_mutex_lock(card);3650 3651	ucontrol->value.integer.value[0] =3652		snd_soc_dapm_get_pin_status(&card->dapm, pin);3653 3654	snd_soc_dapm_mutex_unlock(card);3655 3656	return 0;3657}3658EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);3659 3660/**3661 * snd_soc_dapm_put_pin_switch - Set information for a pin switch3662 *3663 * @kcontrol: mixer control3664 * @ucontrol: Value3665 */3666int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,3667				struct snd_ctl_elem_value *ucontrol)3668{3669	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);3670	const char *pin = (const char *)kcontrol->private_value;3671	int ret;3672 3673	snd_soc_dapm_mutex_lock(card);3674	ret = __snd_soc_dapm_set_pin(&card->dapm, pin,3675				     !!ucontrol->value.integer.value[0]);3676	snd_soc_dapm_mutex_unlock(card);3677 3678	snd_soc_dapm_sync(&card->dapm);3679	return ret;3680}3681EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);3682 3683struct snd_soc_dapm_widget *3684snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,3685			 const struct snd_soc_dapm_widget *widget)3686{3687	enum snd_soc_dapm_direction dir;3688	struct snd_soc_dapm_widget *w;3689	int ret = -ENOMEM;3690 3691	w = dapm_cnew_widget(widget, soc_dapm_prefix(dapm));3692	if (!w)3693		goto cnew_failed;3694 3695	switch (w->id) {3696	case snd_soc_dapm_regulator_supply:3697		w->regulator = devm_regulator_get(dapm->dev, widget->name);3698		if (IS_ERR(w->regulator)) {3699			ret = PTR_ERR(w->regulator);3700			goto request_failed;3701		}3702 3703		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {3704			ret = regulator_allow_bypass(w->regulator, true);3705			if (ret != 0)3706				dev_warn(dapm->dev,3707					 "ASoC: Failed to bypass %s: %d\n",3708					 w->name, ret);3709		}3710		break;3711	case snd_soc_dapm_pinctrl:3712		w->pinctrl = devm_pinctrl_get(dapm->dev);3713		if (IS_ERR(w->pinctrl)) {3714			ret = PTR_ERR(w->pinctrl);3715			goto request_failed;3716		}3717 3718		/* set to sleep_state when initializing */3719		dapm_pinctrl_event(w, NULL, SND_SOC_DAPM_POST_PMD);3720		break;3721	case snd_soc_dapm_clock_supply:3722		w->clk = devm_clk_get(dapm->dev, widget->name);3723		if (IS_ERR(w->clk)) {3724			ret = PTR_ERR(w->clk);3725			goto request_failed;3726		}3727		break;3728	default:3729		break;3730	}3731 3732	switch (w->id) {3733	case snd_soc_dapm_mic:3734		w->is_ep = SND_SOC_DAPM_EP_SOURCE;3735		w->power_check = dapm_generic_check_power;3736		break;3737	case snd_soc_dapm_input:3738		if (!dapm->card->fully_routed)3739			w->is_ep = SND_SOC_DAPM_EP_SOURCE;3740		w->power_check = dapm_generic_check_power;3741		break;3742	case snd_soc_dapm_spk:3743	case snd_soc_dapm_hp:3744		w->is_ep = SND_SOC_DAPM_EP_SINK;3745		w->power_check = dapm_generic_check_power;3746		break;3747	case snd_soc_dapm_output:3748		if (!dapm->card->fully_routed)3749			w->is_ep = SND_SOC_DAPM_EP_SINK;3750		w->power_check = dapm_generic_check_power;3751		break;3752	case snd_soc_dapm_vmid:3753	case snd_soc_dapm_siggen:3754		w->is_ep = SND_SOC_DAPM_EP_SOURCE;3755		w->power_check = dapm_always_on_check_power;3756		break;3757	case snd_soc_dapm_sink:3758		w->is_ep = SND_SOC_DAPM_EP_SINK;3759		w->power_check = dapm_always_on_check_power;3760		break;3761 3762	case snd_soc_dapm_mux:3763	case snd_soc_dapm_demux:3764	case snd_soc_dapm_switch:3765	case snd_soc_dapm_mixer:3766	case snd_soc_dapm_mixer_named_ctl:3767	case snd_soc_dapm_adc:3768	case snd_soc_dapm_aif_out:3769	case snd_soc_dapm_dac:3770	case snd_soc_dapm_aif_in:3771	case snd_soc_dapm_pga:3772	case snd_soc_dapm_buffer:3773	case snd_soc_dapm_scheduler:3774	case snd_soc_dapm_effect:3775	case snd_soc_dapm_src:3776	case snd_soc_dapm_asrc:3777	case snd_soc_dapm_encoder:3778	case snd_soc_dapm_decoder:3779	case snd_soc_dapm_out_drv:3780	case snd_soc_dapm_micbias:3781	case snd_soc_dapm_line:3782	case snd_soc_dapm_dai_link:3783	case snd_soc_dapm_dai_out:3784	case snd_soc_dapm_dai_in:3785		w->power_check = dapm_generic_check_power;3786		break;3787	case snd_soc_dapm_supply:3788	case snd_soc_dapm_regulator_supply:3789	case snd_soc_dapm_pinctrl:3790	case snd_soc_dapm_clock_supply:3791	case snd_soc_dapm_kcontrol:3792		w->is_supply = 1;3793		w->power_check = dapm_supply_check_power;3794		break;3795	default:3796		w->power_check = dapm_always_on_check_power;3797		break;3798	}3799 3800	w->dapm = dapm;3801	INIT_LIST_HEAD(&w->list);3802	INIT_LIST_HEAD(&w->dirty);3803	/* see for_each_card_widgets */3804	list_add_tail(&w->list, &dapm->card->widgets);3805 3806	snd_soc_dapm_for_each_direction(dir) {3807		INIT_LIST_HEAD(&w->edges[dir]);3808		w->endpoints[dir] = -1;3809	}3810 3811	/* machine layer sets up unconnected pins and insertions */3812	w->connected = 1;3813	return w;3814 3815request_failed:3816	dev_err_probe(dapm->dev, ret, "ASoC: Failed to request %s\n",3817		      w->name);3818	kfree_const(w->name);3819	kfree_const(w->sname);3820	kfree(w);3821cnew_failed:3822	return ERR_PTR(ret);3823}3824 3825/**3826 * snd_soc_dapm_new_control - create new dapm control3827 * @dapm: DAPM context3828 * @widget: widget template3829 *3830 * Creates new DAPM control based upon a template.3831 *3832 * Returns a widget pointer on success or an error pointer on failure3833 */3834struct snd_soc_dapm_widget *3835snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,3836			 const struct snd_soc_dapm_widget *widget)3837{3838	struct snd_soc_dapm_widget *w;3839 3840	snd_soc_dapm_mutex_lock(dapm);3841	w = snd_soc_dapm_new_control_unlocked(dapm, widget);3842	snd_soc_dapm_mutex_unlock(dapm);3843 3844	return w;3845}3846EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);3847 3848/**3849 * snd_soc_dapm_new_controls - create new dapm controls3850 * @dapm: DAPM context3851 * @widget: widget array3852 * @num: number of widgets3853 *3854 * Creates new DAPM controls based upon the templates.3855 *3856 * Returns 0 for success else error.3857 */3858int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,3859	const struct snd_soc_dapm_widget *widget,3860	unsigned int num)3861{3862	int i;3863	int ret = 0;3864 3865	snd_soc_dapm_mutex_lock_root(dapm);3866	for (i = 0; i < num; i++) {3867		struct snd_soc_dapm_widget *w = snd_soc_dapm_new_control_unlocked(dapm, widget);3868		if (IS_ERR(w)) {3869			ret = PTR_ERR(w);3870			break;3871		}3872		widget++;3873	}3874	snd_soc_dapm_mutex_unlock(dapm);3875	return ret;3876}3877EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);3878 3879static int3880snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w,3881			       struct snd_pcm_substream *substream)3882{3883	struct snd_soc_dapm_path *path;3884	struct snd_soc_dai *source, *sink;3885	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);3886	const struct snd_soc_pcm_stream *config = NULL;3887	struct snd_pcm_runtime *runtime = NULL;3888	unsigned int fmt;3889	int ret;3890 3891	/*3892	 * NOTE3893	 *3894	 * snd_pcm_hw_params is quite large (608 bytes on arm64) and is3895	 * starting to get a bit excessive for allocation on the stack,3896	 * especially when you're building with some of the KASAN type3897	 * stuff that increases stack usage.3898	 * So, we use kzalloc()/kfree() for params in this function.3899	 */3900	struct snd_pcm_hw_params *params __free(kfree) = kzalloc(sizeof(*params),3901								 GFP_KERNEL);3902	if (!params)3903		return -ENOMEM;3904 3905	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);3906	if (!runtime)3907		return -ENOMEM;3908 3909	substream->runtime = runtime;3910 3911	substream->stream = SNDRV_PCM_STREAM_CAPTURE;3912	snd_soc_dapm_widget_for_each_source_path(w, path) {3913		source = path->source->priv;3914 3915		ret = snd_soc_dai_startup(source, substream);3916		if (ret < 0)3917			return ret;3918 3919		snd_soc_dai_activate(source, substream->stream);3920	}3921 3922	substream->stream = SNDRV_PCM_STREAM_PLAYBACK;3923	snd_soc_dapm_widget_for_each_sink_path(w, path) {3924		sink = path->sink->priv;3925 3926		ret = snd_soc_dai_startup(sink, substream);3927		if (ret < 0)3928			return ret;3929 3930		snd_soc_dai_activate(sink, substream->stream);3931	}3932 3933	substream->hw_opened = 1;3934 3935	/*3936	 * Note: getting the config after .startup() gives a chance to3937	 * either party on the link to alter the configuration if3938	 * necessary3939	 */3940	config = rtd->dai_link->c2c_params + rtd->c2c_params_select;3941	if (!config) {3942		dev_err(w->dapm->dev, "ASoC: link config missing\n");3943		return -EINVAL;3944	}3945 3946	/* Be a little careful as we don't want to overflow the mask array */3947	if (!config->formats) {3948		dev_warn(w->dapm->dev, "ASoC: Invalid format was specified\n");3949 3950		return -EINVAL;3951	}3952 3953	fmt = ffs(config->formats) - 1;3954 3955	snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt);3956	hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min =3957		config->rate_min;3958	hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max =3959		config->rate_max;3960	hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min3961		= config->channels_min;3962	hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max3963		= config->channels_max;3964 3965	substream->stream = SNDRV_PCM_STREAM_CAPTURE;3966	snd_soc_dapm_widget_for_each_source_path(w, path) {3967		source = path->source->priv;3968 3969		ret = snd_soc_dai_hw_params(source, substream, params);3970		if (ret < 0)3971			return ret;3972 3973		dapm_update_dai_unlocked(substream, params, source);3974	}3975 3976	substream->stream = SNDRV_PCM_STREAM_PLAYBACK;3977	snd_soc_dapm_widget_for_each_sink_path(w, path) {3978		sink = path->sink->priv;3979 3980		ret = snd_soc_dai_hw_params(sink, substream, params);3981		if (ret < 0)3982			return ret;3983 3984		dapm_update_dai_unlocked(substream, params, sink);3985	}3986 3987	runtime->format = params_format(params);3988	runtime->subformat = params_subformat(params);3989	runtime->channels = params_channels(params);3990	runtime->rate = params_rate(params);3991 3992	return 0;3993}3994 3995static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,3996				  struct snd_kcontrol *kcontrol, int event)3997{3998	struct snd_soc_dapm_path *path;3999	struct snd_soc_dai *source, *sink;4000	struct snd_pcm_substream *substream = w->priv;4001	int ret = 0, saved_stream = substream->stream;4002 4003	if (WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) ||4004		    list_empty(&w->edges[SND_SOC_DAPM_DIR_IN])))4005		return -EINVAL;4006 4007	switch (event) {4008	case SND_SOC_DAPM_PRE_PMU:4009		ret = snd_soc_dai_link_event_pre_pmu(w, substream);4010		if (ret < 0)4011			goto out;4012 4013		break;4014 4015	case SND_SOC_DAPM_POST_PMU:4016		snd_soc_dapm_widget_for_each_sink_path(w, path) {4017			sink = path->sink->priv;4018 4019			snd_soc_dai_digital_mute(sink, 0, SNDRV_PCM_STREAM_PLAYBACK);4020			ret = 0;4021		}4022		break;4023 4024	case SND_SOC_DAPM_PRE_PMD:4025		snd_soc_dapm_widget_for_each_sink_path(w, path) {4026			sink = path->sink->priv;4027 4028			snd_soc_dai_digital_mute(sink, 1, SNDRV_PCM_STREAM_PLAYBACK);4029			ret = 0;4030		}4031 4032		substream->stream = SNDRV_PCM_STREAM_CAPTURE;4033		snd_soc_dapm_widget_for_each_source_path(w, path) {4034			source = path->source->priv;4035			snd_soc_dai_hw_free(source, substream, 0);4036		}4037 4038		substream->stream = SNDRV_PCM_STREAM_PLAYBACK;4039		snd_soc_dapm_widget_for_each_sink_path(w, path) {4040			sink = path->sink->priv;4041			snd_soc_dai_hw_free(sink, substream, 0);4042		}4043 4044		substream->stream = SNDRV_PCM_STREAM_CAPTURE;4045		snd_soc_dapm_widget_for_each_source_path(w, path) {4046			source = path->source->priv;4047			snd_soc_dai_deactivate(source, substream->stream);4048			snd_soc_dai_shutdown(source, substream, 0);4049		}4050 4051		substream->stream = SNDRV_PCM_STREAM_PLAYBACK;4052		snd_soc_dapm_widget_for_each_sink_path(w, path) {4053			sink = path->sink->priv;4054			snd_soc_dai_deactivate(sink, substream->stream);4055			snd_soc_dai_shutdown(sink, substream, 0);4056		}4057		break;4058 4059	case SND_SOC_DAPM_POST_PMD:4060		kfree(substream->runtime);4061		substream->runtime = NULL;4062		break;4063 4064	default:4065		WARN(1, "Unknown event %d\n", event);4066		ret = -EINVAL;4067	}4068 4069out:4070	/* Restore the substream direction */4071	substream->stream = saved_stream;4072	return ret;4073}4074 4075static int snd_soc_dapm_dai_link_get(struct snd_kcontrol *kcontrol,4076			  struct snd_ctl_elem_value *ucontrol)4077{4078	struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);4079	struct snd_soc_pcm_runtime *rtd = w->priv;4080 4081	ucontrol->value.enumerated.item[0] = rtd->c2c_params_select;4082 4083	return 0;4084}4085 4086static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol,4087			  struct snd_ctl_elem_value *ucontrol)4088{4089	struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);4090	struct snd_soc_pcm_runtime *rtd = w->priv;4091 4092	/* Can't change the config when widget is already powered */4093	if (w->power)4094		return -EBUSY;4095 4096	if (ucontrol->value.enumerated.item[0] == rtd->c2c_params_select)4097		return 0;4098 4099	if (ucontrol->value.enumerated.item[0] >= rtd->dai_link->num_c2c_params)4100		return -EINVAL;4101 4102	rtd->c2c_params_select = ucontrol->value.enumerated.item[0];4103 4104	return 1;4105}4106 4107static void4108snd_soc_dapm_free_kcontrol(struct snd_soc_card *card,4109			unsigned long *private_value,4110			int num_c2c_params,4111			const char **w_param_text)4112{4113	int count;4114 4115	devm_kfree(card->dev, (void *)*private_value);4116 4117	if (!w_param_text)4118		return;4119 4120	for (count = 0 ; count < num_c2c_params; count++)4121		devm_kfree(card->dev, (void *)w_param_text[count]);4122	devm_kfree(card->dev, w_param_text);4123}4124 4125static struct snd_kcontrol_new *4126snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card,4127			char *link_name,4128			const struct snd_soc_pcm_stream *c2c_params,4129			int num_c2c_params, const char **w_param_text,4130			unsigned long *private_value)4131{4132	struct soc_enum w_param_enum[] = {4133		SOC_ENUM_SINGLE(0, 0, 0, NULL),4134	};4135	struct snd_kcontrol_new kcontrol_dai_link[] = {4136		SOC_ENUM_EXT(NULL, w_param_enum[0],4137			     snd_soc_dapm_dai_link_get,4138			     snd_soc_dapm_dai_link_put),4139	};4140	struct snd_kcontrol_new *kcontrol_news;4141	const struct snd_soc_pcm_stream *config = c2c_params;4142	int count;4143 4144	for (count = 0 ; count < num_c2c_params; count++) {4145		if (!config->stream_name) {4146			dev_warn(card->dapm.dev,4147				"ASoC: anonymous config %d for dai link %s\n",4148				count, link_name);4149			w_param_text[count] =4150				devm_kasprintf(card->dev, GFP_KERNEL,4151					       "Anonymous Configuration %d",4152					       count);4153		} else {4154			w_param_text[count] = devm_kmemdup(card->dev,4155						config->stream_name,4156						strlen(config->stream_name) + 1,4157						GFP_KERNEL);4158		}4159		if (!w_param_text[count])4160			goto outfree_w_param;4161		config++;4162	}4163 4164	w_param_enum[0].items = num_c2c_params;4165	w_param_enum[0].texts = w_param_text;4166 4167	*private_value =4168		(unsigned long) devm_kmemdup(card->dev,4169			(void *)(kcontrol_dai_link[0].private_value),4170			sizeof(struct soc_enum), GFP_KERNEL);4171	if (!*private_value) {4172		dev_err(card->dev, "ASoC: Failed to create control for %s widget\n",4173			link_name);4174		goto outfree_w_param;4175	}4176	kcontrol_dai_link[0].private_value = *private_value;4177	/* duplicate kcontrol_dai_link on heap so that memory persists */4178	kcontrol_news = devm_kmemdup(card->dev, &kcontrol_dai_link[0],4179					sizeof(struct snd_kcontrol_new),4180					GFP_KERNEL);4181	if (!kcontrol_news) {4182		dev_err(card->dev, "ASoC: Failed to create control for %s widget\n",4183			link_name);4184		goto outfree_w_param;4185	}4186	return kcontrol_news;4187 4188outfree_w_param:4189	snd_soc_dapm_free_kcontrol(card, private_value, num_c2c_params, w_param_text);4190	return NULL;4191}4192 4193static struct snd_soc_dapm_widget *4194snd_soc_dapm_new_dai(struct snd_soc_card *card,4195		     struct snd_pcm_substream *substream,4196		     char *id)4197{4198	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);4199	struct snd_soc_dapm_widget template;4200	struct snd_soc_dapm_widget *w;4201	const struct snd_kcontrol_new *kcontrol_news;4202	int num_kcontrols;4203	const char **w_param_text;4204	unsigned long private_value = 0;4205	char *link_name;4206	int ret = -ENOMEM;4207 4208	link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s",4209				   rtd->dai_link->name, id);4210	if (!link_name)4211		goto name_fail;4212 4213	/* allocate memory for control, only in case of multiple configs */4214	w_param_text	= NULL;4215	kcontrol_news	= NULL;4216	num_kcontrols	= 0;4217	if (rtd->dai_link->num_c2c_params > 1) {4218		w_param_text = devm_kcalloc(card->dev,4219					    rtd->dai_link->num_c2c_params,4220					    sizeof(char *), GFP_KERNEL);4221		if (!w_param_text)4222			goto param_fail;4223 4224		num_kcontrols = 1;4225		kcontrol_news = snd_soc_dapm_alloc_kcontrol(card, link_name,4226							    rtd->dai_link->c2c_params,4227							    rtd->dai_link->num_c2c_params,4228							    w_param_text, &private_value);4229		if (!kcontrol_news)4230			goto param_fail;4231	}4232 4233	memset(&template, 0, sizeof(template));4234	template.reg		= SND_SOC_NOPM;4235	template.id		= snd_soc_dapm_dai_link;4236	template.name		= link_name;4237	template.event		= snd_soc_dai_link_event;4238	template.event_flags	= SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |4239				  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD;4240	template.kcontrol_news	= kcontrol_news;4241	template.num_kcontrols	= num_kcontrols;4242 4243	dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name);4244 4245	w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template);4246	if (IS_ERR(w)) {4247		ret = PTR_ERR(w);4248		goto outfree_kcontrol_news;4249	}4250 4251	w->priv = substream;4252 4253	return w;4254 4255outfree_kcontrol_news:4256	devm_kfree(card->dev, (void *)template.kcontrol_news);4257	snd_soc_dapm_free_kcontrol(card, &private_value,4258				   rtd->dai_link->num_c2c_params, w_param_text);4259param_fail:4260	devm_kfree(card->dev, link_name);4261name_fail:4262	dev_err(rtd->dev, "ASoC: Failed to create %s-%s widget: %d\n",4263		rtd->dai_link->name, id, ret);4264	return ERR_PTR(ret);4265}4266 4267/**4268 * snd_soc_dapm_new_dai_widgets - Create new DAPM widgets4269 * @dapm: DAPM context4270 * @dai: parent DAI4271 *4272 * Returns 0 on success, error code otherwise.4273 */4274int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,4275				 struct snd_soc_dai *dai)4276{4277	struct snd_soc_dapm_widget template;4278	struct snd_soc_dapm_widget *w;4279 4280	WARN_ON(dapm->dev != dai->dev);4281 4282	memset(&template, 0, sizeof(template));4283	template.reg = SND_SOC_NOPM;4284 4285	if (dai->driver->playback.stream_name) {4286		template.id = snd_soc_dapm_dai_in;4287		template.name = dai->driver->playback.stream_name;4288		template.sname = dai->driver->playback.stream_name;4289 4290		dev_dbg(dai->dev, "ASoC: adding %s widget\n",4291			template.name);4292 4293		w = snd_soc_dapm_new_control_unlocked(dapm, &template);4294		if (IS_ERR(w))4295			return PTR_ERR(w);4296 4297		w->priv = dai;4298		snd_soc_dai_set_widget_playback(dai, w);4299	}4300 4301	if (dai->driver->capture.stream_name) {4302		template.id = snd_soc_dapm_dai_out;4303		template.name = dai->driver->capture.stream_name;4304		template.sname = dai->driver->capture.stream_name;4305 4306		dev_dbg(dai->dev, "ASoC: adding %s widget\n",4307			template.name);4308 4309		w = snd_soc_dapm_new_control_unlocked(dapm, &template);4310		if (IS_ERR(w))4311			return PTR_ERR(w);4312 4313		w->priv = dai;4314		snd_soc_dai_set_widget_capture(dai, w);4315	}4316 4317	return 0;4318}4319EXPORT_SYMBOL_GPL(snd_soc_dapm_new_dai_widgets);4320 4321int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)4322{4323	struct snd_soc_dapm_widget *dai_w, *w;4324	struct snd_soc_dapm_widget *src, *sink;4325	struct snd_soc_dai *dai;4326 4327	/* For each DAI widget... */4328	for_each_card_widgets(card, dai_w) {4329		switch (dai_w->id) {4330		case snd_soc_dapm_dai_in:4331		case snd_soc_dapm_dai_out:4332			break;4333		default:4334			continue;4335		}4336 4337		/* let users know there is no DAI to link */4338		if (!dai_w->priv) {4339			dev_dbg(card->dev, "dai widget %s has no DAI\n",4340				dai_w->name);4341			continue;4342		}4343 4344		dai = dai_w->priv;4345 4346		/* ...find all widgets with the same stream and link them */4347		for_each_card_widgets(card, w) {4348			if (w->dapm != dai_w->dapm)4349				continue;4350 4351			switch (w->id) {4352			case snd_soc_dapm_dai_in:4353			case snd_soc_dapm_dai_out:4354				continue;4355			default:4356				break;4357			}4358 4359			if (!w->sname || !strstr(w->sname, dai_w->sname))4360				continue;4361 4362			if (dai_w->id == snd_soc_dapm_dai_in) {4363				src = dai_w;4364				sink = w;4365			} else {4366				src = w;4367				sink = dai_w;4368			}4369			dev_dbg(dai->dev, "%s -> %s\n", src->name, sink->name);4370			snd_soc_dapm_add_path(w->dapm, src, sink, NULL, NULL);4371		}4372	}4373 4374	return 0;4375}4376 4377static void dapm_connect_dai_routes(struct snd_soc_dapm_context *dapm,4378				    struct snd_soc_dai *src_dai,4379				    struct snd_soc_dapm_widget *src,4380				    struct snd_soc_dapm_widget *dai,4381				    struct snd_soc_dai *sink_dai,4382				    struct snd_soc_dapm_widget *sink)4383{4384	dev_dbg(dapm->dev, "connected DAI link %s:%s -> %s:%s\n",4385		src_dai->component->name, src->name,4386		sink_dai->component->name, sink->name);4387 4388	if (dai) {4389		snd_soc_dapm_add_path(dapm, src, dai, NULL, NULL);4390		src = dai;4391	}4392 4393	snd_soc_dapm_add_path(dapm, src, sink, NULL, NULL);4394}4395 4396static void dapm_connect_dai_pair(struct snd_soc_card *card,4397				  struct snd_soc_pcm_runtime *rtd,4398				  struct snd_soc_dai *codec_dai,4399				  struct snd_soc_dai *cpu_dai)4400{4401	struct snd_soc_dai_link *dai_link = rtd->dai_link;4402	struct snd_soc_dapm_widget *codec, *cpu;4403	struct snd_soc_dai *src_dai[]		= { cpu_dai,	codec_dai };4404	struct snd_soc_dai *sink_dai[]		= { codec_dai,	cpu_dai };4405	struct snd_soc_dapm_widget **src[]	= { &cpu,	&codec };4406	struct snd_soc_dapm_widget **sink[]	= { &codec,	&cpu };4407	char *widget_name[]			= { "playback",	"capture" };4408	int stream;4409 4410	for_each_pcm_streams(stream) {4411		int stream_cpu, stream_codec;4412 4413		stream_cpu	= snd_soc_get_stream_cpu(dai_link, stream);4414		stream_codec	= stream;4415 4416		/* connect BE DAI playback if widgets are valid */4417		cpu	= snd_soc_dai_get_widget(cpu_dai,	stream_cpu);4418		codec	= snd_soc_dai_get_widget(codec_dai,	stream_codec);4419 4420		if (!cpu || !codec)4421			continue;4422 4423		/* special handling for [Codec2Codec] */4424		if (dai_link->c2c_params && !rtd->c2c_widget[stream]) {4425			struct snd_pcm_substream *substream = rtd->pcm->streams[stream].substream;4426			struct snd_soc_dapm_widget *dai = snd_soc_dapm_new_dai(card, substream,4427									       widget_name[stream]);4428 4429			if (IS_ERR(dai))4430				continue;4431 4432			rtd->c2c_widget[stream] = dai;4433		}4434 4435		dapm_connect_dai_routes(&card->dapm, src_dai[stream], *src[stream],4436					rtd->c2c_widget[stream],4437					sink_dai[stream], *sink[stream]);4438	}4439}4440 4441static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,4442	int event)4443{4444	struct snd_soc_dapm_widget *w;4445 4446	w = snd_soc_dai_get_widget(dai, stream);4447 4448	if (w) {4449		unsigned int ep;4450 4451		dapm_mark_dirty(w, "stream event");4452 4453		if (w->id == snd_soc_dapm_dai_in) {4454			ep = SND_SOC_DAPM_EP_SOURCE;4455			dapm_widget_invalidate_input_paths(w);4456		} else {4457			ep = SND_SOC_DAPM_EP_SINK;4458			dapm_widget_invalidate_output_paths(w);4459		}4460 4461		switch (event) {4462		case SND_SOC_DAPM_STREAM_START:4463			w->active = 1;4464			w->is_ep = ep;4465			break;4466		case SND_SOC_DAPM_STREAM_STOP:4467			w->active = 0;4468			w->is_ep = 0;4469			break;4470		case SND_SOC_DAPM_STREAM_SUSPEND:4471		case SND_SOC_DAPM_STREAM_RESUME:4472		case SND_SOC_DAPM_STREAM_PAUSE_PUSH:4473		case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:4474			break;4475		}4476	}4477}4478 4479void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)4480{4481	struct snd_soc_pcm_runtime *rtd;4482	struct snd_soc_dai *cpu_dai;4483	struct snd_soc_dai *codec_dai;4484 4485	/* for each BE DAI link... */4486	for_each_card_rtds(card, rtd)  {4487		struct snd_soc_dai_link_ch_map *ch_maps;4488		int i;4489 4490		/*4491		 * dynamic FE links have no fixed DAI mapping.4492		 * CODEC<->CODEC links have no direct connection.4493		 */4494		if (rtd->dai_link->dynamic)4495			continue;4496 4497		/*4498		 * see4499		 *	soc.h :: [dai_link->ch_maps Image sample]4500		 */4501		for_each_rtd_ch_maps(rtd, i, ch_maps) {4502			cpu_dai   = snd_soc_rtd_to_cpu(rtd,   ch_maps->cpu);4503			codec_dai = snd_soc_rtd_to_codec(rtd, ch_maps->codec);4504 4505			dapm_connect_dai_pair(card, rtd, codec_dai, cpu_dai);4506		}4507	}4508}4509 4510static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,4511	int event)4512{4513	struct snd_soc_dai *dai;4514	int i;4515 4516	for_each_rtd_dais(rtd, i, dai)4517		soc_dapm_dai_stream_event(dai, stream, event);4518 4519	dapm_power_widgets(rtd->card, event);4520}4521 4522/**4523 * snd_soc_dapm_stream_event - send a stream event to the dapm core4524 * @rtd: PCM runtime data4525 * @stream: stream name4526 * @event: stream event4527 *4528 * Sends a stream event to the dapm core. The core then makes any4529 * necessary widget power changes.4530 *4531 * Returns 0 for success else error.4532 */4533void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,4534			      int event)4535{4536	struct snd_soc_card *card = rtd->card;4537 4538	snd_soc_dapm_mutex_lock(card);4539	soc_dapm_stream_event(rtd, stream, event);4540	snd_soc_dapm_mutex_unlock(card);4541}4542 4543void snd_soc_dapm_stream_stop(struct snd_soc_pcm_runtime *rtd, int stream)4544{4545	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {4546		if (snd_soc_runtime_ignore_pmdown_time(rtd)) {4547			/* powered down playback stream now */4548			snd_soc_dapm_stream_event(rtd,4549						  SNDRV_PCM_STREAM_PLAYBACK,4550						  SND_SOC_DAPM_STREAM_STOP);4551		} else {4552			/* start delayed pop wq here for playback streams */4553			rtd->pop_wait = 1;4554			queue_delayed_work(system_power_efficient_wq,4555					   &rtd->delayed_work,4556					   msecs_to_jiffies(rtd->pmdown_time));4557		}4558	} else {4559		/* capture streams can be powered down now */4560		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,4561					  SND_SOC_DAPM_STREAM_STOP);4562	}4563}4564EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_stop);4565 4566/**4567 * snd_soc_dapm_enable_pin_unlocked - enable pin.4568 * @dapm: DAPM context4569 * @pin: pin name4570 *4571 * Enables input/output pin and its parents or children widgets iff there is4572 * a valid audio route and active audio stream.4573 *4574 * Requires external locking.4575 *4576 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to4577 * do any widget power switching.4578 */4579int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,4580				   const char *pin)4581{4582	return snd_soc_dapm_set_pin(dapm, pin, 1);4583}4584EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked);4585 4586/**4587 * snd_soc_dapm_enable_pin - enable pin.4588 * @dapm: DAPM context4589 * @pin: pin name4590 *4591 * Enables input/output pin and its parents or children widgets iff there is4592 * a valid audio route and active audio stream.4593 *4594 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to4595 * do any widget power switching.4596 */4597int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)4598{4599	int ret;4600 4601	snd_soc_dapm_mutex_lock(dapm);4602 4603	ret = snd_soc_dapm_set_pin(dapm, pin, 1);4604 4605	snd_soc_dapm_mutex_unlock(dapm);4606 4607	return ret;4608}4609EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);4610 4611/**4612 * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled4613 * @dapm: DAPM context4614 * @pin: pin name4615 *4616 * Enables input/output pin regardless of any other state.  This is4617 * intended for use with microphone bias supplies used in microphone4618 * jack detection.4619 *4620 * Requires external locking.4621 *4622 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to4623 * do any widget power switching.4624 */4625int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,4626					 const char *pin)4627{4628	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);4629 4630	if (!w) {4631		dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);4632		return -EINVAL;4633	}4634 4635	dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin);4636	if (!w->connected) {4637		/*4638		 * w->force does not affect the number of input or output paths,4639		 * so we only have to recheck if w->connected is changed4640		 */4641		dapm_widget_invalidate_input_paths(w);4642		dapm_widget_invalidate_output_paths(w);4643		w->connected = 1;4644	}4645	w->force = 1;4646	dapm_mark_dirty(w, "force enable");4647 4648	return 0;4649}4650EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked);4651 4652/**4653 * snd_soc_dapm_force_enable_pin - force a pin to be enabled4654 * @dapm: DAPM context4655 * @pin: pin name4656 *4657 * Enables input/output pin regardless of any other state.  This is4658 * intended for use with microphone bias supplies used in microphone4659 * jack detection.4660 *4661 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to4662 * do any widget power switching.4663 */4664int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,4665				  const char *pin)4666{4667	int ret;4668 4669	snd_soc_dapm_mutex_lock(dapm);4670 4671	ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);4672 4673	snd_soc_dapm_mutex_unlock(dapm);4674 4675	return ret;4676}4677EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);4678 4679/**4680 * snd_soc_dapm_disable_pin_unlocked - disable pin.4681 * @dapm: DAPM context4682 * @pin: pin name4683 *4684 * Disables input/output pin and its parents or children widgets.4685 *4686 * Requires external locking.4687 *4688 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to4689 * do any widget power switching.4690 */4691int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,4692				    const char *pin)4693{4694	return snd_soc_dapm_set_pin(dapm, pin, 0);4695}4696EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked);4697 4698/**4699 * snd_soc_dapm_disable_pin - disable pin.4700 * @dapm: DAPM context4701 * @pin: pin name4702 *4703 * Disables input/output pin and its parents or children widgets.4704 *4705 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to4706 * do any widget power switching.4707 */4708int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,4709			     const char *pin)4710{4711	int ret;4712 4713	snd_soc_dapm_mutex_lock(dapm);4714 4715	ret = snd_soc_dapm_set_pin(dapm, pin, 0);4716 4717	snd_soc_dapm_mutex_unlock(dapm);4718 4719	return ret;4720}4721EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);4722 4723/**4724 * snd_soc_dapm_nc_pin_unlocked - permanently disable pin.4725 * @dapm: DAPM context4726 * @pin: pin name4727 *4728 * Marks the specified pin as being not connected, disabling it along4729 * any parent or child widgets.  At present this is identical to4730 * snd_soc_dapm_disable_pin() but in future it will be extended to do4731 * additional things such as disabling controls which only affect4732 * paths through the pin.4733 *4734 * Requires external locking.4735 *4736 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to4737 * do any widget power switching.4738 */4739int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,4740			       const char *pin)4741{4742	return snd_soc_dapm_set_pin(dapm, pin, 0);4743}4744EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked);4745 4746/**4747 * snd_soc_dapm_nc_pin - permanently disable pin.4748 * @dapm: DAPM context4749 * @pin: pin name4750 *4751 * Marks the specified pin as being not connected, disabling it along4752 * any parent or child widgets.  At present this is identical to4753 * snd_soc_dapm_disable_pin() but in future it will be extended to do4754 * additional things such as disabling controls which only affect4755 * paths through the pin.4756 *4757 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to4758 * do any widget power switching.4759 */4760int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)4761{4762	int ret;4763 4764	snd_soc_dapm_mutex_lock(dapm);4765 4766	ret = snd_soc_dapm_set_pin(dapm, pin, 0);4767 4768	snd_soc_dapm_mutex_unlock(dapm);4769 4770	return ret;4771}4772EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);4773 4774/**4775 * snd_soc_dapm_get_pin_status - get audio pin status4776 * @dapm: DAPM context4777 * @pin: audio signal pin endpoint (or start point)4778 *4779 * Get audio pin status - connected or disconnected.4780 *4781 * Returns 1 for connected otherwise 0.4782 */4783int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,4784				const char *pin)4785{4786	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);4787 4788	if (w)4789		return w->connected;4790 4791	return 0;4792}4793EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);4794 4795/**4796 * snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint4797 * @dapm: DAPM context4798 * @pin: audio signal pin endpoint (or start point)4799 *4800 * Mark the given endpoint or pin as ignoring suspend.  When the4801 * system is disabled a path between two endpoints flagged as ignoring4802 * suspend will not be disabled.  The path must already be enabled via4803 * normal means at suspend time, it will not be turned on if it was not4804 * already enabled.4805 */4806int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,4807				const char *pin)4808{4809	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, false);4810 4811	if (!w) {4812		dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);4813		return -EINVAL;4814	}4815 4816	w->ignore_suspend = 1;4817 4818	return 0;4819}4820EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);4821 4822/**4823 * snd_soc_dapm_free - free dapm resources4824 * @dapm: DAPM context4825 *4826 * Free all dapm widgets and resources.4827 */4828void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm)4829{4830	dapm_debugfs_cleanup(dapm);4831	dapm_free_widgets(dapm);4832	list_del(&dapm->list);4833}4834EXPORT_SYMBOL_GPL(snd_soc_dapm_free);4835 4836void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm,4837		       struct snd_soc_card *card,4838		       struct snd_soc_component *component)4839{4840	dapm->card		= card;4841	dapm->component		= component;4842	dapm->bias_level	= SND_SOC_BIAS_OFF;4843 4844	if (component) {4845		dapm->dev		= component->dev;4846		dapm->idle_bias_off	= !component->driver->idle_bias_on;4847		dapm->suspend_bias_off	= component->driver->suspend_bias_off;4848	} else {4849		dapm->dev		= card->dev;4850	}4851 4852	INIT_LIST_HEAD(&dapm->list);4853	/* see for_each_card_dapms */4854	list_add(&dapm->list, &card->dapm_list);4855}4856EXPORT_SYMBOL_GPL(snd_soc_dapm_init);4857 4858static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm)4859{4860	struct snd_soc_card *card = dapm->card;4861	struct snd_soc_dapm_widget *w;4862	LIST_HEAD(down_list);4863	int powerdown = 0;4864 4865	snd_soc_dapm_mutex_lock_root(card);4866 4867	for_each_card_widgets(dapm->card, w) {4868		if (w->dapm != dapm)4869			continue;4870		if (w->power) {4871			dapm_seq_insert(w, &down_list, false);4872			w->new_power = 0;4873			powerdown = 1;4874		}4875	}4876 4877	/* If there were no widgets to power down we're already in4878	 * standby.4879	 */4880	if (powerdown) {4881		if (dapm->bias_level == SND_SOC_BIAS_ON)4882			snd_soc_dapm_set_bias_level(dapm,4883						    SND_SOC_BIAS_PREPARE);4884		dapm_seq_run(card, &down_list, 0, false);4885		if (dapm->bias_level == SND_SOC_BIAS_PREPARE)4886			snd_soc_dapm_set_bias_level(dapm,4887						    SND_SOC_BIAS_STANDBY);4888	}4889 4890	snd_soc_dapm_mutex_unlock(card);4891}4892 4893/*4894 * snd_soc_dapm_shutdown - callback for system shutdown4895 */4896void snd_soc_dapm_shutdown(struct snd_soc_card *card)4897{4898	struct snd_soc_dapm_context *dapm;4899 4900	for_each_card_dapms(card, dapm) {4901		if (dapm != &card->dapm) {4902			soc_dapm_shutdown_dapm(dapm);4903			if (dapm->bias_level == SND_SOC_BIAS_STANDBY)4904				snd_soc_dapm_set_bias_level(dapm,4905							    SND_SOC_BIAS_OFF);4906		}4907	}4908 4909	soc_dapm_shutdown_dapm(&card->dapm);4910	if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY)4911		snd_soc_dapm_set_bias_level(&card->dapm,4912					    SND_SOC_BIAS_OFF);4913}4914 4915/* Module information */4916MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");4917MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");4918MODULE_LICENSE("GPL");4919