soc-dapm.c 114.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// SPDX-License-Identifier: GPL-2.0+
//
// soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management
//
// Copyright 2005 Wolfson Microelectronics PLC.
// Author: Liam Girdwood <lrg@slimlogic.co.uk>
//
//  Features:
//    o Changes power status of internal codec blocks depending on the
//      dynamic configuration of codec internal audio paths and active
//      DACs/ADCs.
//    o Platform power domain - can support external components i.e. amps and
//      mic/headphone insertion events.
//    o Automatic Mic Bias support
//    o Jack insertion power event initiation - e.g. hp insertion will enable
//      sinks, dacs, etc
//    o Delayed power down of audio subsystem to reduce pops between a quick
//      device reopen.
19 20 21 22

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
23
#include <linux/async.h>
24 25 26 27 28
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
#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 36 37
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
L
Liam Girdwood 已提交
38
#include <sound/soc.h>
39 40
#include <sound/initval.h>

M
Mark Brown 已提交
41 42
#include <trace/events/asoc.h>

43 44
#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;

45 46 47 48 49 50 51
#define SND_SOC_DAPM_DIR_REVERSE(x) ((x == SND_SOC_DAPM_DIR_IN) ? \
	SND_SOC_DAPM_DIR_OUT : SND_SOC_DAPM_DIR_IN)

#define snd_soc_dapm_for_each_direction(dir) \
	for ((dir) = SND_SOC_DAPM_DIR_IN; (dir) <= SND_SOC_DAPM_DIR_OUT; \
		(dir)++)

52 53 54 55 56
static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
	struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
	const char *control,
	int (*connected)(struct snd_soc_dapm_widget *source,
			 struct snd_soc_dapm_widget *sink));
57

58
struct snd_soc_dapm_widget *
59 60 61
snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
			 const struct snd_soc_dapm_widget *widget);

62 63
struct snd_soc_dapm_widget *
snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
64 65
			 const struct snd_soc_dapm_widget *widget);

66 67
/* dapm power sequences - make this per codec in the future */
static int dapm_up_seq[] = {
68
	[snd_soc_dapm_pre] = 0,
69
	[snd_soc_dapm_regulator_supply] = 1,
70
	[snd_soc_dapm_pinctrl] = 1,
71
	[snd_soc_dapm_clock_supply] = 1,
72 73
	[snd_soc_dapm_supply] = 2,
	[snd_soc_dapm_micbias] = 3,
74
	[snd_soc_dapm_dai_link] = 2,
75 76 77 78 79 80
	[snd_soc_dapm_dai_in] = 4,
	[snd_soc_dapm_dai_out] = 4,
	[snd_soc_dapm_aif_in] = 4,
	[snd_soc_dapm_aif_out] = 4,
	[snd_soc_dapm_mic] = 5,
	[snd_soc_dapm_mux] = 6,
81
	[snd_soc_dapm_demux] = 6,
82 83 84 85 86 87 88 89 90 91 92 93
	[snd_soc_dapm_dac] = 7,
	[snd_soc_dapm_switch] = 8,
	[snd_soc_dapm_mixer] = 8,
	[snd_soc_dapm_mixer_named_ctl] = 8,
	[snd_soc_dapm_pga] = 9,
	[snd_soc_dapm_adc] = 10,
	[snd_soc_dapm_out_drv] = 11,
	[snd_soc_dapm_hp] = 11,
	[snd_soc_dapm_spk] = 11,
	[snd_soc_dapm_line] = 11,
	[snd_soc_dapm_kcontrol] = 12,
	[snd_soc_dapm_post] = 13,
94
};
95

96
static int dapm_down_seq[] = {
97
	[snd_soc_dapm_pre] = 0,
98 99 100 101 102 103
	[snd_soc_dapm_kcontrol] = 1,
	[snd_soc_dapm_adc] = 2,
	[snd_soc_dapm_hp] = 3,
	[snd_soc_dapm_spk] = 3,
	[snd_soc_dapm_line] = 3,
	[snd_soc_dapm_out_drv] = 3,
104
	[snd_soc_dapm_pga] = 4,
105
	[snd_soc_dapm_switch] = 5,
106
	[snd_soc_dapm_mixer_named_ctl] = 5,
107 108 109 110 111
	[snd_soc_dapm_mixer] = 5,
	[snd_soc_dapm_dac] = 6,
	[snd_soc_dapm_mic] = 7,
	[snd_soc_dapm_micbias] = 8,
	[snd_soc_dapm_mux] = 9,
112
	[snd_soc_dapm_demux] = 9,
113 114
	[snd_soc_dapm_aif_in] = 10,
	[snd_soc_dapm_aif_out] = 10,
115 116
	[snd_soc_dapm_dai_in] = 10,
	[snd_soc_dapm_dai_out] = 10,
117 118
	[snd_soc_dapm_dai_link] = 11,
	[snd_soc_dapm_supply] = 12,
119
	[snd_soc_dapm_clock_supply] = 13,
120
	[snd_soc_dapm_pinctrl] = 13,
121 122
	[snd_soc_dapm_regulator_supply] = 13,
	[snd_soc_dapm_post] = 14,
123 124
};

125 126 127 128 129 130
static void dapm_assert_locked(struct snd_soc_dapm_context *dapm)
{
	if (dapm->card && dapm->card->instantiated)
		lockdep_assert_held(&dapm->card->dapm_mutex);
}

131
static void pop_wait(u32 pop_time)
132 133 134 135 136
{
	if (pop_time)
		schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
}

137
static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
138 139
{
	va_list args;
140
	char *buf;
141

142 143
	if (!pop_time)
		return;
144

145 146 147
	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (buf == NULL)
		return;
148

149 150
	va_start(args, fmt);
	vsnprintf(buf, PAGE_SIZE, fmt, args);
151
	dev_info(dev, "%s", buf);
152
	va_end(args);
153 154

	kfree(buf);
155 156
}

157 158 159 160 161
static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)
{
	return !list_empty(&w->dirty);
}

162
static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
163
{
164 165
	dapm_assert_locked(w->dapm);

166 167 168
	if (!dapm_dirty_widget(w)) {
		dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",
			 w->name, reason);
169
		list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);
170
	}
171 172
}

173
/*
174 175 176 177 178
 * Common implementation for dapm_widget_invalidate_input_paths() and
 * dapm_widget_invalidate_output_paths(). The function is inlined since the
 * combined size of the two specialized functions is only marginally larger then
 * the size of the generic function and at the same time the fast path of the
 * specialized functions is significantly smaller than the generic function.
179
 */
180 181
static __always_inline void dapm_widget_invalidate_paths(
	struct snd_soc_dapm_widget *w, enum snd_soc_dapm_direction dir)
182
{
183 184
	enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir);
	struct snd_soc_dapm_widget *node;
185 186 187 188 189
	struct snd_soc_dapm_path *p;
	LIST_HEAD(list);

	dapm_assert_locked(w->dapm);

190
	if (w->endpoints[dir] == -1)
191 192 193
		return;

	list_add_tail(&w->work_list, &list);
194
	w->endpoints[dir] = -1;
195 196

	list_for_each_entry(w, &list, work_list) {
197
		snd_soc_dapm_widget_for_each_path(w, dir, p) {
198 199
			if (p->is_supply || p->weak || !p->connect)
				continue;
200 201 202 203
			node = p->node[rdir];
			if (node->endpoints[dir] != -1) {
				node->endpoints[dir] = -1;
				list_add_tail(&node->work_list, &list);
204 205 206 207 208
			}
		}
	}
}

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
/*
 * dapm_widget_invalidate_input_paths() - Invalidate the cached number of
 *  input paths
 * @w: The widget for which to invalidate the cached number of input paths
 *
 * Resets the cached number of inputs for the specified widget and all widgets
 * that can be reached via outcoming paths from the widget.
 *
 * This function must be called if the number of output paths for a widget might
 * have changed. E.g. if the source state of a widget changes or a path is added
 * or activated with the widget as the sink.
 */
static void dapm_widget_invalidate_input_paths(struct snd_soc_dapm_widget *w)
{
	dapm_widget_invalidate_paths(w, SND_SOC_DAPM_DIR_IN);
}

226 227 228 229 230 231 232 233 234 235 236 237 238 239
/*
 * dapm_widget_invalidate_output_paths() - Invalidate the cached number of
 *  output paths
 * @w: The widget for which to invalidate the cached number of output paths
 *
 * Resets the cached number of outputs for the specified widget and all widgets
 * that can be reached via incoming paths from the widget.
 *
 * This function must be called if the number of output paths for a widget might
 * have changed. E.g. if the sink state of a widget changes or a path is added
 * or activated with the widget as the source.
 */
static void dapm_widget_invalidate_output_paths(struct snd_soc_dapm_widget *w)
{
240
	dapm_widget_invalidate_paths(w, SND_SOC_DAPM_DIR_OUT);
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
}

/*
 * dapm_path_invalidate() - Invalidates the cached number of inputs and outputs
 *  for the widgets connected to a path
 * @p: The path to invalidate
 *
 * Resets the cached number of inputs for the sink of the path and the cached
 * number of outputs for the source of the path.
 *
 * This function must be called when a path is added, removed or the connected
 * state changes.
 */
static void dapm_path_invalidate(struct snd_soc_dapm_path *p)
{
	/*
	 * Weak paths or supply paths do not influence the number of input or
	 * output paths of their neighbors.
	 */
	if (p->weak || p->is_supply)
		return;

	/*
	 * The number of connected endpoints is the sum of the number of
	 * connected endpoints of all neighbors. If a node with 0 connected
	 * endpoints is either connected or disconnected that sum won't change,
	 * so there is no need to re-check the path.
	 */
269
	if (p->source->endpoints[SND_SOC_DAPM_DIR_IN] != 0)
270
		dapm_widget_invalidate_input_paths(p->sink);
271
	if (p->sink->endpoints[SND_SOC_DAPM_DIR_OUT] != 0)
272 273 274
		dapm_widget_invalidate_output_paths(p->source);
}

275
void dapm_mark_endpoints_dirty(struct snd_soc_card *card)
276 277 278 279 280 281
{
	struct snd_soc_dapm_widget *w;

	mutex_lock(&card->dapm_mutex);

	list_for_each_entry(w, &card->widgets, list) {
282
		if (w->is_ep) {
283
			dapm_mark_dirty(w, "Rechecking endpoints");
284
			if (w->is_ep & SND_SOC_DAPM_EP_SINK)
285
				dapm_widget_invalidate_output_paths(w);
286
			if (w->is_ep & SND_SOC_DAPM_EP_SOURCE)
287 288
				dapm_widget_invalidate_input_paths(w);
		}
289 290 291 292
	}

	mutex_unlock(&card->dapm_mutex);
}
293
EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty);
294

295
/* create a new dapm widget */
296
static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
297 298
	const struct snd_soc_dapm_widget *_widget)
{
299
	return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
300 301
}

302
struct dapm_kcontrol_data {
303
	unsigned int value;
304
	struct snd_soc_dapm_widget *widget;
305
	struct list_head paths;
306
	struct snd_soc_dapm_widget_list *wlist;
307 308 309
};

static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
310
	struct snd_kcontrol *kcontrol, const char *ctrl_name)
311 312
{
	struct dapm_kcontrol_data *data;
313
	struct soc_mixer_control *mc;
314
	struct soc_enum *e;
315 316
	const char *name;
	int ret;
317

318
	data = kzalloc(sizeof(*data), GFP_KERNEL);
319
	if (!data)
320 321
		return -ENOMEM;

322
	INIT_LIST_HEAD(&data->paths);
323

324 325 326 327 328 329
	switch (widget->id) {
	case snd_soc_dapm_switch:
	case snd_soc_dapm_mixer:
	case snd_soc_dapm_mixer_named_ctl:
		mc = (struct soc_mixer_control *)kcontrol->private_value;

330 331 332 333 334
		if (mc->autodisable && snd_soc_volsw_is_stereo(mc))
			dev_warn(widget->dapm->dev,
				 "ASoC: Unsupported stereo autodisable control '%s'\n",
				 ctrl_name);

335 336 337
		if (mc->autodisable) {
			struct snd_soc_dapm_widget template;

338
			name = kasprintf(GFP_KERNEL, "%s %s", ctrl_name,
339 340 341 342 343 344
					 "Autodisable");
			if (!name) {
				ret = -ENOMEM;
				goto err_data;
			}

345 346 347 348 349 350 351 352 353 354
			memset(&template, 0, sizeof(template));
			template.reg = mc->reg;
			template.mask = (1 << fls(mc->max)) - 1;
			template.shift = mc->shift;
			if (mc->invert)
				template.off_val = mc->max;
			else
				template.off_val = 0;
			template.on_val = template.off_val;
			template.id = snd_soc_dapm_kcontrol;
355
			template.name = name;
356

357 358
			data->value = template.on_val;

359 360
			data->widget =
				snd_soc_dapm_new_control_unlocked(widget->dapm,
361
				&template);
362
			kfree(name);
363 364 365 366
			if (IS_ERR(data->widget)) {
				ret = PTR_ERR(data->widget);
				goto err_data;
			}
367 368
		}
		break;
369
	case snd_soc_dapm_demux:
370 371 372 373 374 375
	case snd_soc_dapm_mux:
		e = (struct soc_enum *)kcontrol->private_value;

		if (e->autodisable) {
			struct snd_soc_dapm_widget template;

376
			name = kasprintf(GFP_KERNEL, "%s %s", ctrl_name,
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
					 "Autodisable");
			if (!name) {
				ret = -ENOMEM;
				goto err_data;
			}

			memset(&template, 0, sizeof(template));
			template.reg = e->reg;
			template.mask = e->mask << e->shift_l;
			template.shift = e->shift_l;
			template.off_val = snd_soc_enum_item_to_val(e, 0);
			template.on_val = template.off_val;
			template.id = snd_soc_dapm_kcontrol;
			template.name = name;

			data->value = template.on_val;

394 395
			data->widget = snd_soc_dapm_new_control_unlocked(
						widget->dapm, &template);
396
			kfree(name);
397 398 399 400
			if (IS_ERR(data->widget)) {
				ret = PTR_ERR(data->widget);
				goto err_data;
			}
401 402 403 404 405

			snd_soc_dapm_add_path(widget->dapm, data->widget,
					      widget, NULL, NULL);
		}
		break;
406 407 408 409
	default:
		break;
	}

410 411 412
	kcontrol->private_data = data;

	return 0;
413 414 415 416

err_data:
	kfree(data);
	return ret;
417 418 419 420 421
}

static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);
422 423

	list_del(&data->paths);
424
	kfree(data->wlist);
425 426 427 428 429 430 431 432
	kfree(data);
}

static struct snd_soc_dapm_widget_list *dapm_kcontrol_get_wlist(
	const struct snd_kcontrol *kcontrol)
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);

433
	return data->wlist;
434 435 436 437 438 439
}

static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol,
	struct snd_soc_dapm_widget *widget)
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
440 441
	struct snd_soc_dapm_widget_list *new_wlist;
	unsigned int n;
442

443 444 445 446 447 448 449 450
	if (data->wlist)
		n = data->wlist->num_widgets + 1;
	else
		n = 1;

	new_wlist = krealloc(data->wlist,
			sizeof(*new_wlist) + sizeof(widget) * n, GFP_KERNEL);
	if (!new_wlist)
451 452
		return -ENOMEM;

453 454
	new_wlist->widgets[n - 1] = widget;
	new_wlist->num_widgets = n;
455

456
	data->wlist = new_wlist;
457 458 459 460

	return 0;
}

461 462 463 464 465 466
static void dapm_kcontrol_add_path(const struct snd_kcontrol *kcontrol,
	struct snd_soc_dapm_path *path)
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);

	list_add_tail(&path->list_kcontrol, &data->paths);
467 468 469 470 471 472 473 474 475 476
}

static bool dapm_kcontrol_is_powered(const struct snd_kcontrol *kcontrol)
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);

	if (!data->widget)
		return true;

	return data->widget->power;
477 478 479 480 481 482 483 484 485 486 487 488 489 490
}

static struct list_head *dapm_kcontrol_get_path_list(
	const struct snd_kcontrol *kcontrol)
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);

	return &data->paths;
}

#define dapm_kcontrol_for_each_path(path, kcontrol) \
	list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \
		list_kcontrol)

491
unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)
492 493 494 495 496
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);

	return data->value;
}
497
EXPORT_SYMBOL_GPL(dapm_kcontrol_get_value);
498 499 500 501 502 503 504 505 506

static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
	unsigned int value)
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);

	if (data->value == value)
		return false;

507 508 509
	if (data->widget)
		data->widget->on_val = value;

510 511 512 513 514
	data->value = value;

	return true;
}

515 516 517 518 519 520 521 522 523 524 525 526
/**
 * snd_soc_dapm_kcontrol_widget() - Returns the widget associated to a
 *   kcontrol
 * @kcontrol: The kcontrol
 */
struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_widget(
				struct snd_kcontrol *kcontrol)
{
	return dapm_kcontrol_get_wlist(kcontrol)->widgets[0];
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_widget);

527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
/**
 * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a
 *  kcontrol
 * @kcontrol: The kcontrol
 *
 * Note: This function must only be used on kcontrols that are known to have
 * been registered for a CODEC. Otherwise the behaviour is undefined.
 */
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
	struct snd_kcontrol *kcontrol)
{
	return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm);

542 543 544 545
static void dapm_reset(struct snd_soc_card *card)
{
	struct snd_soc_dapm_widget *w;

546 547
	lockdep_assert_held(&card->dapm_mutex);

548 549 550
	memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));

	list_for_each_entry(w, &card->widgets, list) {
551
		w->new_power = w->power;
552 553 554 555
		w->power_checked = false;
	}
}

556 557 558 559 560 561 562
static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm)
{
	if (!dapm->component)
		return NULL;
	return dapm->component->name_prefix;
}

563
static int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg,
564
	unsigned int *value)
565
{
566
	if (!dapm->component)
567
		return -EIO;
568
	return snd_soc_component_read(dapm->component, reg, value);
569 570
}

571
static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm,
572
	int reg, unsigned int mask, unsigned int value)
573
{
574
	if (!dapm->component)
575
		return -EIO;
M
Mark Brown 已提交
576 577
	return snd_soc_component_update_bits(dapm->component, reg,
					     mask, value);
578 579
}

580 581 582 583 584 585 586 587
static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm,
	int reg, unsigned int mask, unsigned int value)
{
	if (!dapm->component)
		return -EIO;
	return snd_soc_component_test_bits(dapm->component, reg, mask, value);
}

588 589
static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
{
590 591
	if (dapm->component)
		snd_soc_component_async_complete(dapm->component);
592 593
}

594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
static struct snd_soc_dapm_widget *
dapm_wcache_lookup(struct snd_soc_dapm_wcache *wcache, const char *name)
{
	struct snd_soc_dapm_widget *w = wcache->widget;
	struct list_head *wlist;
	const int depth = 2;
	int i = 0;

	if (w) {
		wlist = &w->dapm->card->widgets;

		list_for_each_entry_from(w, wlist, list) {
			if (!strcmp(name, w->name))
				return w;

			if (++i == depth)
				break;
		}
	}

	return NULL;
}

static inline void dapm_wcache_update(struct snd_soc_dapm_wcache *wcache,
				      struct snd_soc_dapm_widget *w)
{
	wcache->widget = w;
}

623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
/**
 * snd_soc_dapm_force_bias_level() - Sets the DAPM bias level
 * @dapm: The DAPM context for which to set the level
 * @level: The level to set
 *
 * Forces the DAPM bias level to a specific state. It will call the bias level
 * callback of DAPM context with the specified level. This will even happen if
 * the context is already at the same level. Furthermore it will not go through
 * the normal bias level sequencing, meaning any intermediate states between the
 * current and the target state will not be entered.
 *
 * Note that the change in bias level is only temporary and the next time
 * snd_soc_dapm_sync() is called the state will be set to the level as
 * determined by the DAPM core. The function is mainly intended to be used to
 * used during probe or resume from suspend to power up the device so
 * initialization can be done, before the DAPM core takes over.
 */
int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm,
	enum snd_soc_bias_level level)
{
	int ret = 0;

	if (dapm->set_bias_level)
		ret = dapm->set_bias_level(dapm, level);

648 649 650
	if (ret == 0)
		dapm->bias_level = level;

651 652 653 654
	return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_bias_level);

655 656
/**
 * snd_soc_dapm_set_bias_level - set the bias level for the system
657
 * @dapm: DAPM context
658 659 660 661 662 663
 * @level: level to configure
 *
 * Configure the bias (power) levels for the SoC audio device.
 *
 * Returns 0 for success else error.
 */
664
static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
L
Liam Girdwood 已提交
665
				       enum snd_soc_bias_level level)
666
{
667
	struct snd_soc_card *card = dapm->card;
668 669
	int ret = 0;

M
Mark Brown 已提交
670 671
	trace_snd_soc_bias_level_start(card, level);

672
	if (card && card->set_bias_level)
673
		ret = card->set_bias_level(card, dapm, level);
674 675 676
	if (ret != 0)
		goto out;

677 678
	if (!card || dapm != &card->dapm)
		ret = snd_soc_dapm_force_bias_level(dapm, level);
679

680 681 682 683
	if (ret != 0)
		goto out;

	if (card && card->set_bias_level_post)
684
		ret = card->set_bias_level_post(card, dapm, level);
685
out:
M
Mark Brown 已提交
686 687
	trace_snd_soc_bias_level_done(card, level);

688 689 690
	return ret;
}

M
Mark Brown 已提交
691
/* connect mux widget to its interconnecting audio paths */
L
Liam Girdwood 已提交
692
static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
693 694
	struct snd_soc_dapm_path *path, const char *control_name,
	struct snd_soc_dapm_widget *w)
695
{
696
	const struct snd_kcontrol_new *kcontrol = &w->kcontrol_news[0];
697
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
698
	unsigned int val, item;
699
	int i;
700

701
	if (e->reg != SND_SOC_NOPM) {
702
		soc_dapm_read(dapm, e->reg, &val);
703 704 705
		val = (val >> e->shift_l) & e->mask;
		item = snd_soc_enum_val_to_item(e, val);
	} else {
706 707 708 709 710 711
		/* since a virtual mux has no backing registers to
		 * decide which path to connect, it will try to match
		 * with the first enumeration.  This is to ensure
		 * that the default mux choice (the first) will be
		 * correctly powered up during initialization.
		 */
712
		item = 0;
713
	}
P
Peter Ujfalusi 已提交
714

715 716 717 718 719 720 721
	i = match_string(e->texts, e->items, control_name);
	if (i < 0)
		return -ENODEV;

	path->name = e->texts[i];
	path->connect = (i == item);
	return 0;
722 723 724

}

725
/* set up initial codec paths */
726 727
static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i,
				       int nth_path)
728 729
{
	struct soc_mixer_control *mc = (struct soc_mixer_control *)
730
		p->sink->kcontrol_news[i].private_value;
731 732 733 734 735 736 737 738
	unsigned int reg = mc->reg;
	unsigned int shift = mc->shift;
	unsigned int max = mc->max;
	unsigned int mask = (1 << fls(max)) - 1;
	unsigned int invert = mc->invert;
	unsigned int val;

	if (reg != SND_SOC_NOPM) {
739
		soc_dapm_read(p->sink->dapm, reg, &val);
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
		/*
		 * The nth_path argument allows this function to know
		 * which path of a kcontrol it is setting the initial
		 * status for. Ideally this would support any number
		 * of paths and channels. But since kcontrols only come
		 * in mono and stereo variants, we are limited to 2
		 * channels.
		 *
		 * The following code assumes for stereo controls the
		 * first path is the left channel, and all remaining
		 * paths are the right channel.
		 */
		if (snd_soc_volsw_is_stereo(mc) && nth_path > 0) {
			if (reg != mc->rreg)
				soc_dapm_read(p->sink->dapm, mc->rreg, &val);
			val = (val >> mc->rshift) & mask;
		} else {
			val = (val >> shift) & mask;
		}
759 760 761 762 763 764 765 766
		if (invert)
			val = max - val;
		p->connect = !!val;
	} else {
		p->connect = 0;
	}
}

M
Mark Brown 已提交
767
/* connect mixer widget to its interconnecting audio paths */
L
Liam Girdwood 已提交
768
static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,
769 770
	struct snd_soc_dapm_path *path, const char *control_name)
{
771
	int i, nth_path = 0;
772 773

	/* search for mixer kcontrol */
774 775 776
	for (i = 0; i < path->sink->num_kcontrols; i++) {
		if (!strcmp(control_name, path->sink->kcontrol_news[i].name)) {
			path->name = path->sink->kcontrol_news[i].name;
777
			dapm_set_mixer_path_status(path, i, nth_path++);
778 779 780 781 782 783
			return 0;
		}
	}
	return -ENODEV;
}

784
static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
785
	struct snd_soc_dapm_widget *kcontrolw,
786 787 788 789 790 791 792 793 794
	const struct snd_kcontrol_new *kcontrol_new,
	struct snd_kcontrol **kcontrol)
{
	struct snd_soc_dapm_widget *w;
	int i;

	*kcontrol = NULL;

	list_for_each_entry(w, &dapm->card->widgets, list) {
795 796
		if (w == kcontrolw || w->dapm != kcontrolw->dapm)
			continue;
797 798 799 800 801 802 803 804 805 806 807 808
		for (i = 0; i < w->num_kcontrols; i++) {
			if (&w->kcontrol_news[i] == kcontrol_new) {
				if (w->kcontrols)
					*kcontrol = w->kcontrols[i];
				return 1;
			}
		}
	}

	return 0;
}

809 810 811 812
/*
 * Determine if a kcontrol is shared. If it is, look it up. If it isn't,
 * create it. Either way, add the widget into the control's widget list
 */
813
static int dapm_create_or_share_kcontrol(struct snd_soc_dapm_widget *w,
814
	int kci)
815
{
816
	struct snd_soc_dapm_context *dapm = w->dapm;
817
	struct snd_card *card = dapm->card->snd_card;
818
	const char *prefix;
819 820 821 822
	size_t prefix_len;
	int shared;
	struct snd_kcontrol *kcontrol;
	bool wname_in_long_name, kcname_in_long_name;
D
Daniel Mack 已提交
823
	char *long_name = NULL;
824
	const char *name;
D
Daniel Mack 已提交
825
	int ret = 0;
826

827
	prefix = soc_dapm_prefix(dapm);
828 829 830 831 832
	if (prefix)
		prefix_len = strlen(prefix) + 1;
	else
		prefix_len = 0;

833 834
	shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],
					 &kcontrol);
835

836 837 838 839 840 841 842 843
	if (!kcontrol) {
		if (shared) {
			wname_in_long_name = false;
			kcname_in_long_name = true;
		} else {
			switch (w->id) {
			case snd_soc_dapm_switch:
			case snd_soc_dapm_mixer:
844
			case snd_soc_dapm_pga:
845
			case snd_soc_dapm_out_drv:
846 847 848 849 850 851 852
				wname_in_long_name = true;
				kcname_in_long_name = true;
				break;
			case snd_soc_dapm_mixer_named_ctl:
				wname_in_long_name = false;
				kcname_in_long_name = true;
				break;
853
			case snd_soc_dapm_demux:
854 855 856 857 858 859
			case snd_soc_dapm_mux:
				wname_in_long_name = true;
				kcname_in_long_name = false;
				break;
			default:
				return -EINVAL;
860
			}
861 862 863 864 865 866 867 868
		}

		if (wname_in_long_name && kcname_in_long_name) {
			/*
			 * The control will get a prefix from the control
			 * creation process but we're also using the same
			 * prefix for widgets so cut the prefix off the
			 * front of the widget name.
869
			 */
870
			long_name = kasprintf(GFP_KERNEL, "%s %s",
871 872
				 w->name + prefix_len,
				 w->kcontrol_news[kci].name);
873
			if (long_name == NULL)
874
				return -ENOMEM;
875 876 877 878 879 880 881 882 883

			name = long_name;
		} else if (wname_in_long_name) {
			long_name = NULL;
			name = w->name + prefix_len;
		} else {
			long_name = NULL;
			name = w->kcontrol_news[kci].name;
		}
884

885
		kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name,
886
					prefix);
D
Daniel Mack 已提交
887 888 889 890 891
		if (!kcontrol) {
			ret = -ENOMEM;
			goto exit_free;
		}

892
		kcontrol->private_free = dapm_kcontrol_free;
893

894
		ret = dapm_kcontrol_data_alloc(w, kcontrol, name);
895 896
		if (ret) {
			snd_ctl_free_one(kcontrol);
D
Daniel Mack 已提交
897
			goto exit_free;
898 899
		}

900 901 902 903 904
		ret = snd_ctl_add(card, kcontrol);
		if (ret < 0) {
			dev_err(dapm->dev,
				"ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
				w->name, name, ret);
D
Daniel Mack 已提交
905
			goto exit_free;
906 907
		}
	}
908

909
	ret = dapm_kcontrol_add_widget(kcontrol, w);
D
Daniel Mack 已提交
910 911
	if (ret == 0)
		w->kcontrols[kci] = kcontrol;
912

D
Daniel Mack 已提交
913 914
exit_free:
	kfree(long_name);
915

D
Daniel Mack 已提交
916
	return ret;
917
}
918

919 920 921 922 923
/* create new dapm mixer control */
static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
{
	int i, ret;
	struct snd_soc_dapm_path *path;
924
	struct dapm_kcontrol_data *data;
925 926 927 928

	/* add kcontrol */
	for (i = 0; i < w->num_kcontrols; i++) {
		/* match name */
929
		snd_soc_dapm_widget_for_each_source_path(w, path) {
930 931 932 933
			/* mixer/mux paths name must match control name */
			if (path->name != (char *)w->kcontrol_news[i].name)
				continue;

934
			if (!w->kcontrols[i]) {
935
				ret = dapm_create_or_share_kcontrol(w, i);
936 937
				if (ret < 0)
					return ret;
938
			}
939

940
			dapm_kcontrol_add_path(w->kcontrols[i], path);
941 942 943 944 945 946 947

			data = snd_kcontrol_chip(w->kcontrols[i]);
			if (data->widget)
				snd_soc_dapm_add_path(data->widget->dapm,
						      data->widget,
						      path->source,
						      NULL, NULL);
948 949
		}
	}
950 951

	return 0;
952 953 954
}

/* create new dapm mux control */
955
static int dapm_new_mux(struct snd_soc_dapm_widget *w)
956
{
957
	struct snd_soc_dapm_context *dapm = w->dapm;
958
	enum snd_soc_dapm_direction dir;
959
	struct snd_soc_dapm_path *path;
960
	const char *type;
961
	int ret;
962

963 964
	switch (w->id) {
	case snd_soc_dapm_mux:
965
		dir = SND_SOC_DAPM_DIR_OUT;
966 967 968
		type = "mux";
		break;
	case snd_soc_dapm_demux:
969
		dir = SND_SOC_DAPM_DIR_IN;
970 971 972 973 974 975
		type = "demux";
		break;
	default:
		return -EINVAL;
	}

976 977
	if (w->num_kcontrols != 1) {
		dev_err(dapm->dev,
978
			"ASoC: %s %s has incorrect number of controls\n", type,
979
			w->name);
980 981 982
		return -EINVAL;
	}

983
	if (list_empty(&w->edges[dir])) {
984
		dev_err(dapm->dev, "ASoC: %s %s has no paths\n", type, w->name);
985
		return -EINVAL;
986
	}
L
Liam Girdwood 已提交
987

988
	ret = dapm_create_or_share_kcontrol(w, 0);
989 990
	if (ret < 0)
		return ret;
991

992 993 994
	snd_soc_dapm_widget_for_each_path(w, dir, path) {
		if (path->name)
			dapm_kcontrol_add_path(w->kcontrols[0], path);
995
	}
996

997
	return 0;
998 999 1000
}

/* create new dapm volume control */
1001
static int dapm_new_pga(struct snd_soc_dapm_widget *w)
1002
{
1003 1004 1005 1006 1007 1008 1009
	int i, ret;

	for (i = 0; i < w->num_kcontrols; i++) {
		ret = dapm_create_or_share_kcontrol(w, i);
		if (ret < 0)
			return ret;
	}
1010

1011
	return 0;
1012 1013
}

1014 1015 1016 1017 1018 1019 1020
/* create new dapm dai link control */
static int dapm_new_dai_link(struct snd_soc_dapm_widget *w)
{
	int i, ret;
	struct snd_kcontrol *kcontrol;
	struct snd_soc_dapm_context *dapm = w->dapm;
	struct snd_card *card = dapm->card->snd_card;
1021
	struct snd_soc_pcm_runtime *rtd = w->priv;
1022 1023

	/* create control for links with > 1 config */
1024
	if (rtd->dai_link->num_params <= 1)
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
		return 0;

	/* add kcontrol */
	for (i = 0; i < w->num_kcontrols; i++) {
		kcontrol = snd_soc_cnew(&w->kcontrol_news[i], w,
					w->name, NULL);
		ret = snd_ctl_add(card, kcontrol);
		if (ret < 0) {
			dev_err(dapm->dev,
				"ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
				w->name, w->kcontrol_news[i].name, ret);
			return ret;
		}
		kcontrol->private_data = w;
		w->kcontrols[i] = kcontrol;
	}

	return 0;
}

1045 1046 1047 1048 1049 1050
/* We implement power down on suspend by checking the power state of
 * the ALSA card - when we are suspending the ALSA state for the card
 * is set to D3.
 */
static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
{
1051
	int level = snd_power_get_state(widget->dapm->card->snd_card);
1052

1053
	switch (level) {
1054 1055
	case SNDRV_CTL_POWER_D3hot:
	case SNDRV_CTL_POWER_D3cold:
1056
		if (widget->ignore_suspend)
1057
			dev_dbg(widget->dapm->dev, "ASoC: %s ignoring suspend\n",
1058
				widget->name);
1059
		return widget->ignore_suspend;
1060 1061 1062 1063 1064
	default:
		return 1;
	}
}

1065 1066
static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list,
	struct list_head *widgets)
1067
{
1068 1069 1070 1071
	struct snd_soc_dapm_widget *w;
	struct list_head *it;
	unsigned int size = 0;
	unsigned int i = 0;
1072

1073 1074
	list_for_each(it, widgets)
		size++;
1075

1076
	*list = kzalloc(struct_size(*list, widgets, size), GFP_KERNEL);
1077
	if (*list == NULL)
1078 1079
		return -ENOMEM;

1080 1081
	list_for_each_entry(w, widgets, work_list)
		(*list)->widgets[i++] = w;
1082

1083 1084 1085
	(*list)->num_widgets = i;

	return 0;
1086 1087
}

1088
/*
1089 1090 1091 1092 1093
 * Common implementation for is_connected_output_ep() and
 * is_connected_input_ep(). The function is inlined since the combined size of
 * the two specialized functions is only marginally larger then the size of the
 * generic function and at the same time the fast path of the specialized
 * functions is significantly smaller than the generic function.
1094
 */
1095 1096
static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget,
	struct list_head *list, enum snd_soc_dapm_direction dir,
1097 1098 1099 1100 1101
	int (*fn)(struct snd_soc_dapm_widget *, struct list_head *,
		  bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,
						enum snd_soc_dapm_direction)),
	bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,
				      enum snd_soc_dapm_direction))
1102
{
1103
	enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir);
1104 1105 1106
	struct snd_soc_dapm_path *path;
	int con = 0;

1107 1108
	if (widget->endpoints[dir] >= 0)
		return widget->endpoints[dir];
1109

1110 1111
	DAPM_UPDATE_STAT(widget, path_checks);

1112 1113 1114 1115
	/* do we need to add this widget to the list ? */
	if (list)
		list_add_tail(&widget->work_list, list);

1116 1117 1118 1119
	if (custom_stop_condition && custom_stop_condition(widget, dir)) {
		widget->endpoints[dir] = 1;
		return widget->endpoints[dir];
	}
1120

1121 1122 1123
	if ((widget->is_ep & SND_SOC_DAPM_DIR_TO_EP(dir)) && widget->connected) {
		widget->endpoints[dir] = snd_soc_dapm_suspend_check(widget);
		return widget->endpoints[dir];
1124 1125
	}

1126
	snd_soc_dapm_widget_for_each_path(widget, rdir, path) {
1127 1128
		DAPM_UPDATE_STAT(widget, neighbour_checks);

1129
		if (path->weak || path->is_supply)
1130 1131
			continue;

M
Mark Brown 已提交
1132 1133 1134
		if (path->walking)
			return 1;

1135
		trace_snd_soc_dapm_path(widget, dir, path);
1136

1137
		if (path->connect) {
M
Mark Brown 已提交
1138
			path->walking = 1;
1139
			con += fn(path->node[dir], list, custom_stop_condition);
M
Mark Brown 已提交
1140
			path->walking = 0;
1141 1142 1143
		}
	}

1144
	widget->endpoints[dir] = con;
1145

1146 1147 1148
	return con;
}

1149 1150 1151
/*
 * Recursively check for a completed path to an active or physically connected
 * output widget. Returns number of complete paths.
1152 1153 1154 1155 1156
 *
 * Optionally, can be supplied with a function acting as a stopping condition.
 * This function takes the dapm widget currently being examined and the walk
 * direction as an arguments, it should return true if the walk should be
 * stopped and false otherwise.
1157 1158
 */
static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
1159 1160 1161
	struct list_head *list,
	bool (*custom_stop_condition)(struct snd_soc_dapm_widget *i,
				      enum snd_soc_dapm_direction))
1162 1163
{
	return is_connected_ep(widget, list, SND_SOC_DAPM_DIR_OUT,
1164
			is_connected_output_ep, custom_stop_condition);
1165 1166
}

1167 1168 1169
/*
 * Recursively check for a completed path to an active or physically connected
 * input widget. Returns number of complete paths.
1170 1171 1172 1173 1174
 *
 * Optionally, can be supplied with a function acting as a stopping condition.
 * This function takes the dapm widget currently being examined and the walk
 * direction as an arguments, it should return true if the walk should be
 * stopped and false otherwise.
1175
 */
1176
static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
1177 1178 1179
	struct list_head *list,
	bool (*custom_stop_condition)(struct snd_soc_dapm_widget *i,
				      enum snd_soc_dapm_direction))
1180
{
1181
	return is_connected_ep(widget, list, SND_SOC_DAPM_DIR_IN,
1182
			is_connected_input_ep, custom_stop_condition);
1183 1184
}

1185 1186 1187 1188 1189
/**
 * snd_soc_dapm_get_connected_widgets - query audio path and it's widgets.
 * @dai: the soc DAI.
 * @stream: stream direction.
 * @list: list of active widgets for this stream.
1190 1191
 * @custom_stop_condition: (optional) a function meant to stop the widget graph
 *                         walk based on custom logic.
1192
 *
1193
 * Queries DAPM graph as to whether a valid audio stream path exists for
1194 1195 1196
 * the initial stream specified by name. This takes into account
 * current mixer and mux kcontrol settings. Creates list of valid widgets.
 *
1197 1198 1199 1200 1201
 * Optionally, can be supplied with a function acting as a stopping condition.
 * This function takes the dapm widget currently being examined and the walk
 * direction as an arguments, it should return true if the walk should be
 * stopped and false otherwise.
 *
1202 1203 1204
 * Returns the number of valid paths or negative error.
 */
int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
1205 1206 1207
	struct snd_soc_dapm_widget_list **list,
	bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,
				      enum snd_soc_dapm_direction))
1208
{
1209
	struct snd_soc_card *card = dai->component->card;
1210
	struct snd_soc_dapm_widget *w;
1211
	LIST_HEAD(widgets);
1212
	int paths;
1213
	int ret;
1214 1215

	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
1216 1217 1218 1219 1220 1221

	/*
	 * For is_connected_{output,input}_ep fully discover the graph we need
	 * to reset the cached number of inputs and outputs.
	 */
	list_for_each_entry(w, &card->widgets, list) {
1222 1223
		w->endpoints[SND_SOC_DAPM_DIR_IN] = -1;
		w->endpoints[SND_SOC_DAPM_DIR_OUT] = -1;
1224
	}
1225

1226
	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1227 1228
		paths = is_connected_output_ep(dai->playback_widget, &widgets,
				custom_stop_condition);
1229
	else
1230 1231
		paths = is_connected_input_ep(dai->capture_widget, &widgets,
				custom_stop_condition);
1232 1233 1234 1235 1236 1237

	/* Drop starting point */
	list_del(widgets.next);

	ret = dapm_widget_list_create(list, &widgets);
	if (ret)
1238
		paths = ret;
1239 1240 1241 1242 1243 1244 1245

	trace_snd_soc_dapm_connected(paths, stream);
	mutex_unlock(&card->dapm_mutex);

	return paths;
}

1246 1247 1248 1249 1250 1251
/*
 * Handler for regulator supply widget.
 */
int dapm_regulator_event(struct snd_soc_dapm_widget *w,
		   struct snd_kcontrol *kcontrol, int event)
{
1252 1253
	int ret;

1254 1255
	soc_dapm_async_complete(w->dapm);

1256
	if (SND_SOC_DAPM_EVENT_ON(event)) {
1257
		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
1258
			ret = regulator_allow_bypass(w->regulator, false);
1259 1260
			if (ret != 0)
				dev_warn(w->dapm->dev,
1261
					 "ASoC: Failed to unbypass %s: %d\n",
1262 1263 1264
					 w->name, ret);
		}

1265
		return regulator_enable(w->regulator);
1266
	} else {
1267
		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
1268
			ret = regulator_allow_bypass(w->regulator, true);
1269 1270
			if (ret != 0)
				dev_warn(w->dapm->dev,
1271
					 "ASoC: Failed to bypass %s: %d\n",
1272 1273 1274
					 w->name, ret);
		}

1275
		return regulator_disable_deferred(w->regulator, w->shift);
1276
	}
1277 1278 1279
}
EXPORT_SYMBOL_GPL(dapm_regulator_event);

1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304
/*
 * Handler for pinctrl widget.
 */
int dapm_pinctrl_event(struct snd_soc_dapm_widget *w,
		       struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_dapm_pinctrl_priv *priv = w->priv;
	struct pinctrl *p = w->pinctrl;
	struct pinctrl_state *s;

	if (!p || !priv)
		return -EIO;

	if (SND_SOC_DAPM_EVENT_ON(event))
		s = pinctrl_lookup_state(p, priv->active_state);
	else
		s = pinctrl_lookup_state(p, priv->sleep_state);

	if (IS_ERR(s))
		return PTR_ERR(s);

	return pinctrl_select_state(p, s);
}
EXPORT_SYMBOL_GPL(dapm_pinctrl_event);

1305 1306 1307 1308 1309 1310 1311 1312 1313
/*
 * Handler for clock supply widget.
 */
int dapm_clock_event(struct snd_soc_dapm_widget *w,
		   struct snd_kcontrol *kcontrol, int event)
{
	if (!w->clk)
		return -EIO;

1314 1315
	soc_dapm_async_complete(w->dapm);

1316
	if (SND_SOC_DAPM_EVENT_ON(event)) {
1317
		return clk_prepare_enable(w->clk);
1318
	} else {
1319
		clk_disable_unprepare(w->clk);
1320 1321
		return 0;
	}
1322

1323
	return 0;
1324 1325 1326
}
EXPORT_SYMBOL_GPL(dapm_clock_event);

1327 1328
static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
{
1329 1330 1331
	if (w->power_checked)
		return w->new_power;

1332
	if (w->force)
1333
		w->new_power = 1;
1334
	else
1335 1336 1337 1338 1339
		w->new_power = w->power_check(w);

	w->power_checked = true;

	return w->new_power;
1340 1341
}

1342
/* Generic check to see if a widget should be powered. */
1343 1344 1345 1346
static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
{
	int in, out;

1347 1348
	DAPM_UPDATE_STAT(w, power_checks);

1349 1350
	in = is_connected_input_ep(w, NULL, NULL);
	out = is_connected_output_ep(w, NULL, NULL);
1351 1352 1353
	return out != 0 && in != 0;
}

1354 1355 1356 1357 1358
/* Check to see if a power supply is needed */
static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
{
	struct snd_soc_dapm_path *path;

1359 1360
	DAPM_UPDATE_STAT(w, power_checks);

1361
	/* Check if one of our outputs is connected */
1362
	snd_soc_dapm_widget_for_each_sink_path(w, path) {
1363 1364
		DAPM_UPDATE_STAT(w, neighbour_checks);

1365 1366 1367
		if (path->weak)
			continue;

1368 1369 1370 1371
		if (path->connected &&
		    !path->connected(path->source, path->sink))
			continue;

1372 1373
		if (dapm_widget_power_check(path->sink))
			return 1;
1374 1375
	}

1376
	return 0;
1377 1378
}

1379 1380
static int dapm_always_on_check_power(struct snd_soc_dapm_widget *w)
{
1381
	return w->connected;
1382 1383
}

1384 1385
static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
			    struct snd_soc_dapm_widget *b,
1386
			    bool power_up)
1387
{
1388 1389 1390 1391 1392 1393 1394
	int *sort;

	if (power_up)
		sort = dapm_up_seq;
	else
		sort = dapm_down_seq;

1395 1396
	if (sort[a->id] != sort[b->id])
		return sort[a->id] - sort[b->id];
1397 1398 1399 1400 1401 1402
	if (a->subseq != b->subseq) {
		if (power_up)
			return a->subseq - b->subseq;
		else
			return b->subseq - a->subseq;
	}
1403 1404
	if (a->reg != b->reg)
		return a->reg - b->reg;
1405 1406
	if (a->dapm != b->dapm)
		return (unsigned long)a->dapm - (unsigned long)b->dapm;
1407

1408 1409
	return 0;
}
1410

1411 1412 1413
/* Insert a widget in order into a DAPM power sequence. */
static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
			    struct list_head *list,
1414
			    bool power_up)
1415 1416 1417 1418
{
	struct snd_soc_dapm_widget *w;

	list_for_each_entry(w, list, power_list)
1419
		if (dapm_seq_compare(new_widget, w, power_up) < 0) {
1420 1421 1422 1423 1424 1425 1426
			list_add_tail(&new_widget->power_list, &w->power_list);
			return;
		}

	list_add_tail(&new_widget->power_list, list);
}

1427
static void dapm_seq_check_event(struct snd_soc_card *card,
1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449
				 struct snd_soc_dapm_widget *w, int event)
{
	const char *ev_name;
	int power, ret;

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		ev_name = "PRE_PMU";
		power = 1;
		break;
	case SND_SOC_DAPM_POST_PMU:
		ev_name = "POST_PMU";
		power = 1;
		break;
	case SND_SOC_DAPM_PRE_PMD:
		ev_name = "PRE_PMD";
		power = 0;
		break;
	case SND_SOC_DAPM_POST_PMD:
		ev_name = "POST_PMD";
		power = 0;
		break;
1450 1451 1452 1453 1454 1455 1456 1457
	case SND_SOC_DAPM_WILL_PMU:
		ev_name = "WILL_PMU";
		power = 1;
		break;
	case SND_SOC_DAPM_WILL_PMD:
		ev_name = "WILL_PMD";
		power = 0;
		break;
1458
	default:
T
Takashi Iwai 已提交
1459
		WARN(1, "Unknown event %d\n", event);
1460 1461 1462
		return;
	}

1463
	if (w->new_power != power)
1464 1465 1466
		return;

	if (w->event && (w->event_flags & event)) {
1467
		pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
1468
			w->name, ev_name);
1469
		soc_dapm_async_complete(w->dapm);
M
Mark Brown 已提交
1470
		trace_snd_soc_dapm_widget_event_start(w, event);
1471
		ret = w->event(w, NULL, event);
M
Mark Brown 已提交
1472
		trace_snd_soc_dapm_widget_event_done(w, event);
1473
		if (ret < 0)
1474
			dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n",
1475 1476 1477 1478
			       ev_name, w->name, ret);
	}
}

1479
/* Apply the coalesced changes from a DAPM sequence */
1480
static void dapm_seq_run_coalesced(struct snd_soc_card *card,
1481
				   struct list_head *pending)
1482
{
1483
	struct snd_soc_dapm_context *dapm;
1484
	struct snd_soc_dapm_widget *w;
1485
	int reg;
1486 1487 1488
	unsigned int value = 0;
	unsigned int mask = 0;

1489 1490 1491
	w = list_first_entry(pending, struct snd_soc_dapm_widget, power_list);
	reg = w->reg;
	dapm = w->dapm;
1492 1493

	list_for_each_entry(w, pending, power_list) {
1494
		WARN_ON(reg != w->reg || dapm != w->dapm);
1495
		w->power = w->new_power;
1496

1497 1498 1499
		mask |= w->mask << w->shift;
		if (w->power)
			value |= w->on_val << w->shift;
1500
		else
1501
			value |= w->off_val << w->shift;
1502

1503
		pop_dbg(dapm->dev, card->pop_time,
1504 1505
			"pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
			w->name, reg, value, mask);
1506

1507
		/* Check for events */
1508 1509
		dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMU);
		dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMD);
1510 1511 1512
	}

	if (reg >= 0) {
1513 1514 1515 1516
		/* Any widget will do, they should all be updating the
		 * same register.
		 */

1517
		pop_dbg(dapm->dev, card->pop_time,
1518
			"pop test : Applying 0x%x/0x%x to %x in %dms\n",
1519 1520
			value, mask, reg, card->pop_time);
		pop_wait(card->pop_time);
1521
		soc_dapm_update_bits(dapm, reg, mask, value);
1522 1523
	}

1524
	list_for_each_entry(w, pending, power_list) {
1525 1526
		dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMU);
		dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMD);
1527
	}
1528
}
1529

1530 1531 1532 1533 1534 1535 1536 1537
/* Apply a DAPM power sequence.
 *
 * We walk over a pre-sorted list of widgets to apply power to.  In
 * order to minimise the number of writes to the device required
 * multiple widgets will be updated in a single write where possible.
 * Currently anything that requires more than a single write is not
 * handled.
 */
1538 1539
static void dapm_seq_run(struct snd_soc_card *card,
	struct list_head *list, int event, bool power_up)
1540 1541
{
	struct snd_soc_dapm_widget *w, *n;
1542
	struct snd_soc_dapm_context *d;
1543 1544
	LIST_HEAD(pending);
	int cur_sort = -1;
1545
	int cur_subseq = -1;
1546
	int cur_reg = SND_SOC_NOPM;
1547
	struct snd_soc_dapm_context *cur_dapm = NULL;
1548
	int ret, i;
1549 1550 1551 1552 1553 1554
	int *sort;

	if (power_up)
		sort = dapm_up_seq;
	else
		sort = dapm_down_seq;
1555

1556 1557 1558 1559
	list_for_each_entry_safe(w, n, list, power_list) {
		ret = 0;

		/* Do we need to apply any queued changes? */
1560
		if (sort[w->id] != cur_sort || w->reg != cur_reg ||
1561
		    w->dapm != cur_dapm || w->subseq != cur_subseq) {
1562
			if (!list_empty(&pending))
1563
				dapm_seq_run_coalesced(card, &pending);
1564

1565 1566 1567 1568
			if (cur_dapm && cur_dapm->seq_notifier) {
				for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
					if (sort[i] == cur_sort)
						cur_dapm->seq_notifier(cur_dapm,
1569 1570
								       i,
								       cur_subseq);
1571 1572
			}

1573 1574 1575
			if (cur_dapm && w->dapm != cur_dapm)
				soc_dapm_async_complete(cur_dapm);

1576 1577
			INIT_LIST_HEAD(&pending);
			cur_sort = -1;
1578
			cur_subseq = INT_MIN;
1579
			cur_reg = SND_SOC_NOPM;
1580
			cur_dapm = NULL;
1581 1582
		}

1583 1584 1585
		switch (w->id) {
		case snd_soc_dapm_pre:
			if (!w->event)
1586 1587
				list_for_each_entry_safe_continue(w, n, list,
								  power_list);
1588

1589
			if (event == SND_SOC_DAPM_STREAM_START)
1590 1591
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_PRE_PMU);
1592
			else if (event == SND_SOC_DAPM_STREAM_STOP)
1593 1594 1595 1596 1597 1598
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_PRE_PMD);
			break;

		case snd_soc_dapm_post:
			if (!w->event)
1599 1600
				list_for_each_entry_safe_continue(w, n, list,
								  power_list);
1601

1602
			if (event == SND_SOC_DAPM_STREAM_START)
1603 1604
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_POST_PMU);
1605
			else if (event == SND_SOC_DAPM_STREAM_STOP)
1606 1607 1608 1609
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_POST_PMD);
			break;

1610
		default:
1611 1612
			/* Queue it up for application */
			cur_sort = sort[w->id];
1613
			cur_subseq = w->subseq;
1614
			cur_reg = w->reg;
1615
			cur_dapm = w->dapm;
1616 1617
			list_move(&w->power_list, &pending);
			break;
1618
		}
1619 1620

		if (ret < 0)
1621
			dev_err(w->dapm->dev,
1622
				"ASoC: Failed to apply widget power: %d\n", ret);
1623
	}
1624 1625

	if (!list_empty(&pending))
1626
		dapm_seq_run_coalesced(card, &pending);
1627 1628 1629 1630 1631

	if (cur_dapm && cur_dapm->seq_notifier) {
		for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
			if (sort[i] == cur_sort)
				cur_dapm->seq_notifier(cur_dapm,
1632
						       i, cur_subseq);
1633
	}
1634 1635 1636 1637

	list_for_each_entry(d, &card->dapm_list, list) {
		soc_dapm_async_complete(d);
	}
1638 1639
}

1640
static void dapm_widget_update(struct snd_soc_card *card)
1641
{
1642
	struct snd_soc_dapm_update *update = card->update;
1643 1644 1645
	struct snd_soc_dapm_widget_list *wlist;
	struct snd_soc_dapm_widget *w = NULL;
	unsigned int wi;
1646 1647
	int ret;

1648
	if (!update || !dapm_kcontrol_is_powered(update->kcontrol))
1649 1650
		return;

1651
	wlist = dapm_kcontrol_get_wlist(update->kcontrol);
1652

1653 1654 1655 1656 1657 1658
	for (wi = 0; wi < wlist->num_widgets; wi++) {
		w = wlist->widgets[wi];

		if (w->event && (w->event_flags & SND_SOC_DAPM_PRE_REG)) {
			ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
			if (ret != 0)
1659
				dev_err(w->dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",
1660 1661
					   w->name, ret);
		}
1662 1663
	}

1664 1665 1666
	if (!w)
		return;

1667 1668
	ret = soc_dapm_update_bits(w->dapm, update->reg, update->mask,
		update->val);
1669
	if (ret < 0)
1670
		dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",
1671
			w->name, ret);
1672

1673 1674 1675 1676 1677 1678 1679 1680 1681
	if (update->has_second_set) {
		ret = soc_dapm_update_bits(w->dapm, update->reg2,
					   update->mask2, update->val2);
		if (ret < 0)
			dev_err(w->dapm->dev,
				"ASoC: %s DAPM update failed: %d\n",
				w->name, ret);
	}

1682 1683 1684 1685 1686 1687
	for (wi = 0; wi < wlist->num_widgets; wi++) {
		w = wlist->widgets[wi];

		if (w->event && (w->event_flags & SND_SOC_DAPM_POST_REG)) {
			ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
			if (ret != 0)
1688
				dev_err(w->dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",
1689 1690
					   w->name, ret);
		}
1691 1692 1693
	}
}

1694 1695 1696 1697 1698 1699 1700 1701
/* Async callback run prior to DAPM sequences - brings to _PREPARE if
 * they're changing state.
 */
static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
{
	struct snd_soc_dapm_context *d = data;
	int ret;

1702
	/* If we're off and we're not supposed to go into STANDBY */
1703 1704
	if (d->bias_level == SND_SOC_BIAS_OFF &&
	    d->target_bias_level != SND_SOC_BIAS_OFF) {
1705 1706 1707
		if (d->dev)
			pm_runtime_get_sync(d->dev);

1708 1709 1710
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
		if (ret != 0)
			dev_err(d->dev,
1711
				"ASoC: Failed to turn on bias: %d\n", ret);
1712 1713
	}

1714 1715 1716 1717 1718
	/* Prepare for a transition to ON or away from ON */
	if ((d->target_bias_level == SND_SOC_BIAS_ON &&
	     d->bias_level != SND_SOC_BIAS_ON) ||
	    (d->target_bias_level != SND_SOC_BIAS_ON &&
	     d->bias_level == SND_SOC_BIAS_ON)) {
1719 1720 1721
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);
		if (ret != 0)
			dev_err(d->dev,
1722
				"ASoC: Failed to prepare bias: %d\n", ret);
1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734
	}
}

/* Async callback run prior to DAPM sequences - brings to their final
 * state.
 */
static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
{
	struct snd_soc_dapm_context *d = data;
	int ret;

	/* If we just powered the last thing off drop to standby bias */
1735 1736 1737
	if (d->bias_level == SND_SOC_BIAS_PREPARE &&
	    (d->target_bias_level == SND_SOC_BIAS_STANDBY ||
	     d->target_bias_level == SND_SOC_BIAS_OFF)) {
1738 1739
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
		if (ret != 0)
1740
			dev_err(d->dev, "ASoC: Failed to apply standby bias: %d\n",
1741 1742
				ret);
	}
1743

1744
	/* If we're in standby and can support bias off then do that */
1745 1746
	if (d->bias_level == SND_SOC_BIAS_STANDBY &&
	    d->target_bias_level == SND_SOC_BIAS_OFF) {
1747 1748
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
		if (ret != 0)
1749 1750
			dev_err(d->dev, "ASoC: Failed to turn off bias: %d\n",
				ret);
1751 1752

		if (d->dev)
1753
			pm_runtime_put(d->dev);
1754 1755 1756
	}

	/* If we just powered up then move to active bias */
1757 1758
	if (d->bias_level == SND_SOC_BIAS_PREPARE &&
	    d->target_bias_level == SND_SOC_BIAS_ON) {
1759 1760
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON);
		if (ret != 0)
1761
			dev_err(d->dev, "ASoC: Failed to apply active bias: %d\n",
1762 1763 1764
				ret);
	}
}
1765

1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
static void dapm_widget_set_peer_power(struct snd_soc_dapm_widget *peer,
				       bool power, bool connect)
{
	/* If a connection is being made or broken then that update
	 * will have marked the peer dirty, otherwise the widgets are
	 * not connected and this update has no impact. */
	if (!connect)
		return;

	/* If the peer is already in the state we're moving to then we
	 * won't have an impact on it. */
	if (power != peer->power)
1778
		dapm_mark_dirty(peer, "peer state change");
1779 1780
}

1781 1782 1783 1784
static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
				  struct list_head *up_list,
				  struct list_head *down_list)
{
1785 1786
	struct snd_soc_dapm_path *path;

1787 1788 1789 1790 1791
	if (w->power == power)
		return;

	trace_snd_soc_dapm_widget_power(w, power);

1792
	/* If we changed our power state perhaps our neigbours changed
1793
	 * also.
1794
	 */
1795
	snd_soc_dapm_widget_for_each_source_path(w, path)
1796 1797
		dapm_widget_set_peer_power(path->source, power, path->connect);

1798 1799
	/* Supplies can't affect their outputs, only their inputs */
	if (!w->is_supply) {
1800
		snd_soc_dapm_widget_for_each_sink_path(w, path)
1801 1802
			dapm_widget_set_peer_power(path->sink, power,
						   path->connect);
1803 1804
	}

1805 1806 1807 1808 1809 1810
	if (power)
		dapm_seq_insert(w, up_list, true);
	else
		dapm_seq_insert(w, down_list, false);
}

1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825
static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
				  struct list_head *up_list,
				  struct list_head *down_list)
{
	int power;

	switch (w->id) {
	case snd_soc_dapm_pre:
		dapm_seq_insert(w, down_list, false);
		break;
	case snd_soc_dapm_post:
		dapm_seq_insert(w, up_list, true);
		break;

	default:
1826
		power = dapm_widget_power_check(w);
1827

1828
		dapm_widget_set_power(w, power, up_list, down_list);
1829 1830 1831 1832
		break;
	}
}

1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848
static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm)
{
	if (dapm->idle_bias_off)
		return true;

	switch (snd_power_get_state(dapm->card->snd_card)) {
	case SNDRV_CTL_POWER_D3hot:
	case SNDRV_CTL_POWER_D3cold:
		return dapm->suspend_bias_off;
	default:
		break;
	}

	return false;
}

1849 1850 1851 1852 1853
/*
 * Scan each dapm widget for complete audio path.
 * A complete path is a route that has valid endpoints i.e.:-
 *
 *  o DAC to output pin.
1854
 *  o Input pin to ADC.
1855 1856 1857
 *  o Input pin to Output pin (bypass, sidetone)
 *  o DAC to ADC (loopback).
 */
1858
static int dapm_power_widgets(struct snd_soc_card *card, int event)
1859 1860
{
	struct snd_soc_dapm_widget *w;
1861
	struct snd_soc_dapm_context *d;
1862 1863
	LIST_HEAD(up_list);
	LIST_HEAD(down_list);
1864
	ASYNC_DOMAIN_EXCLUSIVE(async_domain);
1865
	enum snd_soc_bias_level bias;
1866

1867 1868
	lockdep_assert_held(&card->dapm_mutex);

M
Mark Brown 已提交
1869 1870
	trace_snd_soc_dapm_start(card);

1871
	list_for_each_entry(d, &card->dapm_list, list) {
1872
		if (dapm_idle_bias_off(d))
1873 1874 1875
			d->target_bias_level = SND_SOC_BIAS_OFF;
		else
			d->target_bias_level = SND_SOC_BIAS_STANDBY;
1876
	}
1877

1878
	dapm_reset(card);
1879

1880
	/* Check which widgets we need to power and store them in
1881 1882 1883 1884
	 * lists indicating if they should be powered up or down.  We
	 * only check widgets that have been flagged as dirty but note
	 * that new widgets may be added to the dirty list while we
	 * iterate.
1885
	 */
1886
	list_for_each_entry(w, &card->dapm_dirty, dirty) {
1887
		dapm_power_one_widget(w, &up_list, &down_list);
1888 1889
	}

1890
	list_for_each_entry(w, &card->widgets, list) {
1891 1892 1893 1894 1895 1896 1897 1898 1899
		switch (w->id) {
		case snd_soc_dapm_pre:
		case snd_soc_dapm_post:
			/* These widgets always need to be powered */
			break;
		default:
			list_del_init(&w->dirty);
			break;
		}
1900

1901
		if (w->new_power) {
1902 1903 1904 1905 1906
			d = w->dapm;

			/* Supplies and micbiases only bring the
			 * context up to STANDBY as unless something
			 * else is active and passing audio they
1907 1908 1909
			 * generally don't require full power.  Signal
			 * generators are virtual pins and have no
			 * power impact themselves.
1910 1911
			 */
			switch (w->id) {
1912
			case snd_soc_dapm_siggen:
1913
			case snd_soc_dapm_vmid:
1914
				break;
1915
			case snd_soc_dapm_supply:
1916
			case snd_soc_dapm_regulator_supply:
1917
			case snd_soc_dapm_pinctrl:
1918
			case snd_soc_dapm_clock_supply:
1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930
			case snd_soc_dapm_micbias:
				if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
					d->target_bias_level = SND_SOC_BIAS_STANDBY;
				break;
			default:
				d->target_bias_level = SND_SOC_BIAS_ON;
				break;
			}
		}

	}

1931 1932 1933
	/* Force all contexts in the card to the same bias state if
	 * they're not ground referenced.
	 */
1934
	bias = SND_SOC_BIAS_OFF;
1935
	list_for_each_entry(d, &card->dapm_list, list)
1936 1937
		if (d->target_bias_level > bias)
			bias = d->target_bias_level;
1938
	list_for_each_entry(d, &card->dapm_list, list)
1939
		if (!dapm_idle_bias_off(d))
1940
			d->target_bias_level = bias;
1941

1942
	trace_snd_soc_dapm_walk_done(card);
1943

1944 1945 1946 1947
	/* Run card bias changes at first */
	dapm_pre_sequence_async(&card->dapm, 0);
	/* Run other bias changes in parallel */
	list_for_each_entry(d, &card->dapm_list, list) {
1948
		if (d != &card->dapm && d->bias_level != d->target_bias_level)
1949 1950 1951
			async_schedule_domain(dapm_pre_sequence_async, d,
						&async_domain);
	}
1952
	async_synchronize_full_domain(&async_domain);
1953

1954
	list_for_each_entry(w, &down_list, power_list) {
1955
		dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMD);
1956 1957
	}

1958
	list_for_each_entry(w, &up_list, power_list) {
1959
		dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMU);
1960 1961
	}

1962
	/* Power down widgets first; try to avoid amplifying pops. */
1963
	dapm_seq_run(card, &down_list, event, false);
1964

1965
	dapm_widget_update(card);
1966

1967
	/* Now power up. */
1968
	dapm_seq_run(card, &up_list, event, true);
1969

1970
	/* Run all the bias changes in parallel */
1971
	list_for_each_entry(d, &card->dapm_list, list) {
1972
		if (d != &card->dapm && d->bias_level != d->target_bias_level)
1973 1974 1975
			async_schedule_domain(dapm_post_sequence_async, d,
						&async_domain);
	}
1976
	async_synchronize_full_domain(&async_domain);
1977 1978
	/* Run card bias changes at last */
	dapm_post_sequence_async(&card->dapm, 0);
1979

1980 1981 1982 1983 1984 1985
	/* do we need to notify any clients that DAPM event is complete */
	list_for_each_entry(d, &card->dapm_list, list) {
		if (d->stream_event)
			d->stream_event(d, event);
	}

1986
	pop_dbg(card->dev, card->pop_time,
1987
		"DAPM sequencing finished, waiting %dms\n", card->pop_time);
1988
	pop_wait(card->pop_time);
1989

M
Mark Brown 已提交
1990 1991
	trace_snd_soc_dapm_done(card);

1992
	return 0;
1993 1994
}

1995 1996 1997 1998 1999 2000
#ifdef CONFIG_DEBUG_FS
static ssize_t dapm_widget_power_read_file(struct file *file,
					   char __user *user_buf,
					   size_t count, loff_t *ppos)
{
	struct snd_soc_dapm_widget *w = file->private_data;
2001
	struct snd_soc_card *card = w->dapm->card;
2002
	enum snd_soc_dapm_direction dir, rdir;
2003 2004 2005 2006 2007 2008 2009 2010 2011
	char *buf;
	int in, out;
	ssize_t ret;
	struct snd_soc_dapm_path *p = NULL;

	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

2012 2013
	mutex_lock(&card->dapm_mutex);

2014 2015 2016 2017 2018
	/* Supply widgets are not handled by is_connected_{input,output}_ep() */
	if (w->is_supply) {
		in = 0;
		out = 0;
	} else {
2019 2020
		in = is_connected_input_ep(w, NULL, NULL);
		out = is_connected_output_ep(w, NULL, NULL);
2021
	}
2022

2023 2024 2025
	ret = snprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
		       w->name, w->power ? "On" : "Off",
		       w->force ? " (forced)" : "", in, out);
2026

2027 2028
	if (w->reg >= 0)
		ret += snprintf(buf + ret, PAGE_SIZE - ret,
2029 2030
				" - R%d(0x%x) mask 0x%x",
				w->reg, w->reg, w->mask << w->shift);
2031 2032 2033

	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");

2034 2035 2036 2037
	if (w->sname)
		ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
				w->sname,
				w->active ? "active" : "inactive");
2038

2039 2040 2041
	snd_soc_dapm_for_each_direction(dir) {
		rdir = SND_SOC_DAPM_DIR_REVERSE(dir);
		snd_soc_dapm_widget_for_each_path(w, dir, p) {
2042
			if (p->connected && !p->connected(p->source, p->sink))
2043
				continue;
2044

2045 2046
			if (!p->connect)
				continue;
2047

2048
			ret += snprintf(buf + ret, PAGE_SIZE - ret,
2049 2050
					" %s  \"%s\" \"%s\"\n",
					(rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out",
2051
					p->name ? p->name : "static",
2052 2053
					p->node[rdir]->name);
		}
2054 2055
	}

2056 2057
	mutex_unlock(&card->dapm_mutex);

2058 2059 2060 2061 2062 2063 2064
	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);

	kfree(buf);
	return ret;
}

static const struct file_operations dapm_widget_power_fops = {
2065
	.open = simple_open,
2066
	.read = dapm_widget_power_read_file,
2067
	.llseek = default_llseek,
2068 2069
};

2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089
static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,
				   size_t count, loff_t *ppos)
{
	struct snd_soc_dapm_context *dapm = file->private_data;
	char *level;

	switch (dapm->bias_level) {
	case SND_SOC_BIAS_ON:
		level = "On\n";
		break;
	case SND_SOC_BIAS_PREPARE:
		level = "Prepare\n";
		break;
	case SND_SOC_BIAS_STANDBY:
		level = "Standby\n";
		break;
	case SND_SOC_BIAS_OFF:
		level = "Off\n";
		break;
	default:
T
Takashi Iwai 已提交
2090
		WARN(1, "Unknown bias_level %d\n", dapm->bias_level);
2091 2092 2093 2094 2095 2096 2097 2098 2099
		level = "Unknown\n";
		break;
	}

	return simple_read_from_buffer(user_buf, count, ppos, level,
				       strlen(level));
}

static const struct file_operations dapm_bias_fops = {
2100
	.open = simple_open,
2101 2102 2103 2104
	.read = dapm_bias_read_file,
	.llseek = default_llseek,
};

2105 2106
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
	struct dentry *parent)
2107 2108 2109
{
	struct dentry *d;

2110 2111 2112
	if (!parent)
		return;

2113 2114 2115
	dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);

	if (!dapm->debugfs_dapm) {
2116
		dev_warn(dapm->dev,
2117
		       "ASoC: Failed to create DAPM debugfs directory\n");
2118
		return;
2119
	}
2120

2121 2122 2123 2124 2125 2126
	d = debugfs_create_file("bias_level", 0444,
				dapm->debugfs_dapm, dapm,
				&dapm_bias_fops);
	if (!d)
		dev_warn(dapm->dev,
			 "ASoC: Failed to create bias level debugfs file\n");
2127
}
2128

2129 2130 2131 2132
static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
{
	struct snd_soc_dapm_context *dapm = w->dapm;
	struct dentry *d;
2133

2134 2135 2136 2137 2138 2139 2140 2141 2142 2143
	if (!dapm->debugfs_dapm || !w->name)
		return;

	d = debugfs_create_file(w->name, 0444,
				dapm->debugfs_dapm, w,
				&dapm_widget_power_fops);
	if (!d)
		dev_warn(w->dapm->dev,
			"ASoC: Failed to create %s debugfs file\n",
			w->name);
2144
}
2145

2146 2147 2148 2149 2150
static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
{
	debugfs_remove_recursive(dapm->debugfs_dapm);
}

2151
#else
2152 2153
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
	struct dentry *parent)
2154 2155
{
}
2156 2157 2158 2159 2160

static inline void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
{
}

2161 2162 2163 2164
static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
{
}

2165 2166
#endif

2167 2168 2169 2170
/*
 * soc_dapm_connect_path() - Connects or disconnects a path
 * @path: The path to update
 * @connect: The new connect state of the path. True if the path is connected,
2171
 *  false if it is disconnected.
2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182
 * @reason: The reason why the path changed (for debugging only)
 */
static void soc_dapm_connect_path(struct snd_soc_dapm_path *path,
	bool connect, const char *reason)
{
	if (path->connect == connect)
		return;

	path->connect = connect;
	dapm_mark_dirty(path->source, reason);
	dapm_mark_dirty(path->sink, reason);
2183
	dapm_path_invalidate(path);
2184 2185
}

2186
/* test and update the power status of a mux widget */
2187
static int soc_dapm_mux_update_power(struct snd_soc_card *card,
2188
				 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
2189 2190 2191
{
	struct snd_soc_dapm_path *path;
	int found = 0;
2192
	bool connect;
2193

2194 2195
	lockdep_assert_held(&card->dapm_mutex);

2196
	/* find dapm widget path assoc with kcontrol */
2197
	dapm_kcontrol_for_each_path(path, kcontrol) {
2198 2199
		found = 1;
		/* we now need to match the string in the enum to the path */
2200 2201 2202 2203 2204 2205
		if (!(strcmp(path->name, e->texts[mux])))
			connect = true;
		else
			connect = false;

		soc_dapm_connect_path(path, connect, "mux update");
2206 2207
	}

2208
	if (found)
2209
		dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
2210

2211
	return found;
2212
}
2213

2214
int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
2215 2216
	struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
	struct snd_soc_dapm_update *update)
2217
{
2218
	struct snd_soc_card *card = dapm->card;
2219 2220
	int ret;

2221
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2222
	card->update = update;
2223
	ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
2224
	card->update = NULL;
2225
	mutex_unlock(&card->dapm_mutex);
2226
	if (ret > 0)
2227
		soc_dpcm_runtime_update(card);
2228 2229
	return ret;
}
2230
EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
2231

2232
/* test and update the power status of a mixer or switch widget */
2233
static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
2234 2235
				       struct snd_kcontrol *kcontrol,
				       int connect, int rconnect)
2236 2237 2238 2239
{
	struct snd_soc_dapm_path *path;
	int found = 0;

2240 2241
	lockdep_assert_held(&card->dapm_mutex);

2242
	/* find dapm widget path assoc with kcontrol */
2243
	dapm_kcontrol_for_each_path(path, kcontrol) {
2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269
		/*
		 * Ideally this function should support any number of
		 * paths and channels. But since kcontrols only come
		 * in mono and stereo variants, we are limited to 2
		 * channels.
		 *
		 * The following code assumes for stereo controls the
		 * first path (when 'found == 0') is the left channel,
		 * and all remaining paths (when 'found == 1') are the
		 * right channel.
		 *
		 * A stereo control is signified by a valid 'rconnect'
		 * value, either 0 for unconnected, or >= 0 for connected.
		 * This is chosen instead of using snd_soc_volsw_is_stereo,
		 * so that the behavior of snd_soc_dapm_mixer_update_power
		 * doesn't change even when the kcontrol passed in is
		 * stereo.
		 *
		 * It passes 'connect' as the path connect status for
		 * the left channel, and 'rconnect' for the right
		 * channel.
		 */
		if (found && rconnect >= 0)
			soc_dapm_connect_path(path, rconnect, "mixer update");
		else
			soc_dapm_connect_path(path, connect, "mixer update");
2270 2271 2272
		found = 1;
	}

2273
	if (found)
2274
		dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
2275

2276
	return found;
2277
}
2278

2279
int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
2280 2281
	struct snd_kcontrol *kcontrol, int connect,
	struct snd_soc_dapm_update *update)
2282
{
2283
	struct snd_soc_card *card = dapm->card;
2284 2285
	int ret;

2286
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2287
	card->update = update;
2288
	ret = soc_dapm_mixer_update_power(card, kcontrol, connect, -1);
2289
	card->update = NULL;
2290
	mutex_unlock(&card->dapm_mutex);
2291
	if (ret > 0)
2292
		soc_dpcm_runtime_update(card);
2293 2294
	return ret;
}
2295
EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
2296

2297 2298
static ssize_t dapm_widget_show_component(struct snd_soc_component *cmpnt,
	char *buf)
2299
{
2300
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
2301 2302 2303 2304
	struct snd_soc_dapm_widget *w;
	int count = 0;
	char *state = "not set";

2305 2306 2307 2308 2309 2310 2311
	/* card won't be set for the dummy component, as a spot fix
	 * we're checking for that case specifically here but in future
	 * we will ensure that the dummy component looks like others.
	 */
	if (!cmpnt->card)
		return 0;

2312 2313
	list_for_each_entry(w, &cmpnt->card->widgets, list) {
		if (w->dapm != dapm)
2314
			continue;
2315

2316
		/* only display widgets that burn power */
2317 2318 2319 2320 2321 2322 2323 2324 2325
		switch (w->id) {
		case snd_soc_dapm_hp:
		case snd_soc_dapm_mic:
		case snd_soc_dapm_spk:
		case snd_soc_dapm_line:
		case snd_soc_dapm_micbias:
		case snd_soc_dapm_dac:
		case snd_soc_dapm_adc:
		case snd_soc_dapm_pga:
2326
		case snd_soc_dapm_out_drv:
2327
		case snd_soc_dapm_mixer:
2328
		case snd_soc_dapm_mixer_named_ctl:
2329
		case snd_soc_dapm_supply:
2330
		case snd_soc_dapm_regulator_supply:
2331
		case snd_soc_dapm_pinctrl:
2332
		case snd_soc_dapm_clock_supply:
2333 2334 2335 2336 2337 2338 2339 2340 2341
			if (w->name)
				count += sprintf(buf + count, "%s: %s\n",
					w->name, w->power ? "On":"Off");
		break;
		default:
		break;
		}
	}

2342
	switch (snd_soc_dapm_get_bias_level(dapm)) {
2343 2344
	case SND_SOC_BIAS_ON:
		state = "On";
2345
		break;
2346 2347
	case SND_SOC_BIAS_PREPARE:
		state = "Prepare";
2348
		break;
2349 2350
	case SND_SOC_BIAS_STANDBY:
		state = "Standby";
2351
		break;
2352 2353
	case SND_SOC_BIAS_OFF:
		state = "Off";
2354 2355 2356 2357 2358 2359 2360
		break;
	}
	count += sprintf(buf + count, "PM State: %s\n", state);

	return count;
}

2361 2362 2363 2364 2365
/* show dapm widget status in sys fs */
static ssize_t dapm_widget_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
2366
	struct snd_soc_dai *codec_dai;
2367 2368
	int i, count = 0;

2369 2370
	mutex_lock(&rtd->card->dapm_mutex);

2371 2372
	for_each_rtd_codec_dai(rtd, i, codec_dai) {
		struct snd_soc_component *cmpnt = codec_dai->component;
2373 2374

		count += dapm_widget_show_component(cmpnt, buf + count);
2375 2376
	}

2377 2378
	mutex_unlock(&rtd->card->dapm_mutex);

2379 2380 2381
	return count;
}

J
Joe Perches 已提交
2382
static DEVICE_ATTR_RO(dapm_widget);
2383

2384 2385 2386 2387
struct attribute *soc_dapm_dev_attrs[] = {
	&dev_attr_dapm_widget.attr,
	NULL
};
2388

2389 2390
static void dapm_free_path(struct snd_soc_dapm_path *path)
{
2391 2392
	list_del(&path->list_node[SND_SOC_DAPM_DIR_IN]);
	list_del(&path->list_node[SND_SOC_DAPM_DIR_OUT]);
2393
	list_del(&path->list_kcontrol);
2394 2395 2396 2397
	list_del(&path->list);
	kfree(path);
}

2398 2399 2400
void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w)
{
	struct snd_soc_dapm_path *p, *next_p;
2401
	enum snd_soc_dapm_direction dir;
2402 2403 2404 2405 2406 2407 2408

	list_del(&w->list);
	/*
	 * remove source and sink paths associated to this widget.
	 * While removing the path, remove reference to it from both
	 * source and sink widgets so that path is removed only once.
	 */
2409 2410 2411 2412
	snd_soc_dapm_for_each_direction(dir) {
		snd_soc_dapm_widget_for_each_path_safe(w, dir, p, next_p)
			dapm_free_path(p);
	}
2413 2414

	kfree(w->kcontrols);
2415
	kfree_const(w->name);
2416 2417 2418
	kfree(w);
}

2419 2420 2421 2422 2423 2424
void snd_soc_dapm_reset_cache(struct snd_soc_dapm_context *dapm)
{
	dapm->path_sink_cache.widget = NULL;
	dapm->path_source_cache.widget = NULL;
}

2425
/* free all dapm widgets and resources */
L
Liam Girdwood 已提交
2426
static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
2427 2428 2429
{
	struct snd_soc_dapm_widget *w, *next_w;

2430 2431 2432
	list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
		if (w->dapm != dapm)
			continue;
2433
		snd_soc_dapm_free_widget(w);
2434
	}
2435
	snd_soc_dapm_reset_cache(dapm);
2436 2437
}

2438 2439 2440
static struct snd_soc_dapm_widget *dapm_find_widget(
			struct snd_soc_dapm_context *dapm, const char *pin,
			bool search_other_contexts)
2441 2442
{
	struct snd_soc_dapm_widget *w;
2443
	struct snd_soc_dapm_widget *fallback = NULL;
2444

2445
	list_for_each_entry(w, &dapm->card->widgets, list) {
2446
		if (!strcmp(w->name, pin)) {
2447 2448 2449 2450
			if (w->dapm == dapm)
				return w;
			else
				fallback = w;
2451 2452 2453
		}
	}

2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464
	if (search_other_contexts)
		return fallback;

	return NULL;
}

static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
				const char *pin, int status)
{
	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);

2465 2466
	dapm_assert_locked(dapm);

2467
	if (!w) {
2468
		dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin);
2469
		return -EINVAL;
2470 2471
	}

2472
	if (w->connected != status) {
2473
		dapm_mark_dirty(w, "pin configuration");
2474 2475 2476
		dapm_widget_invalidate_input_paths(w);
		dapm_widget_invalidate_output_paths(w);
	}
2477

2478 2479 2480 2481 2482
	w->connected = status;
	if (status == 0)
		w->force = 0;

	return 0;
2483 2484
}

2485
/**
2486
 * snd_soc_dapm_sync_unlocked - scan and power dapm paths
L
Liam Girdwood 已提交
2487
 * @dapm: DAPM context
2488 2489 2490 2491
 *
 * Walks all dapm audio paths and powers widgets according to their
 * stream or path usage.
 *
2492 2493
 * Requires external locking.
 *
2494 2495
 * Returns 0 for success.
 */
2496
int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm)
2497
{
2498 2499 2500 2501 2502 2503 2504
	/*
	 * Suppress early reports (eg, jacks syncing their state) to avoid
	 * silly DAPM runs during card startup.
	 */
	if (!dapm->card || !dapm->card->instantiated)
		return 0;

2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521
	return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked);

/**
 * snd_soc_dapm_sync - scan and power dapm paths
 * @dapm: DAPM context
 *
 * Walks all dapm audio paths and powers widgets according to their
 * stream or path usage.
 *
 * Returns 0 for success.
 */
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
{
	int ret;

2522
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2523
	ret = snd_soc_dapm_sync_unlocked(dapm);
2524 2525
	mutex_unlock(&dapm->card->dapm_mutex);
	return ret;
2526
}
2527
EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
2528

2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539
/*
 * dapm_update_widget_flags() - Re-compute widget sink and source flags
 * @w: The widget for which to update the flags
 *
 * Some widgets have a dynamic category which depends on which neighbors they
 * are connected to. This function update the category for these widgets.
 *
 * This function must be called whenever a path is added or removed to a widget.
 */
static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w)
{
2540
	enum snd_soc_dapm_direction dir;
2541
	struct snd_soc_dapm_path *p;
2542
	unsigned int ep;
2543 2544 2545

	switch (w->id) {
	case snd_soc_dapm_input:
2546
		/* On a fully routed card an input is never a source */
2547
		if (w->dapm->card->fully_routed)
2548 2549
			return;
		ep = SND_SOC_DAPM_EP_SOURCE;
2550
		snd_soc_dapm_widget_for_each_source_path(w, p) {
2551 2552 2553 2554
			if (p->source->id == snd_soc_dapm_micbias ||
				p->source->id == snd_soc_dapm_mic ||
				p->source->id == snd_soc_dapm_line ||
				p->source->id == snd_soc_dapm_output) {
2555
					ep = 0;
2556 2557 2558 2559 2560
					break;
			}
		}
		break;
	case snd_soc_dapm_output:
2561 2562
		/* On a fully routed card a output is never a sink */
		if (w->dapm->card->fully_routed)
2563 2564
			return;
		ep = SND_SOC_DAPM_EP_SINK;
2565
		snd_soc_dapm_widget_for_each_sink_path(w, p) {
2566 2567 2568 2569
			if (p->sink->id == snd_soc_dapm_spk ||
				p->sink->id == snd_soc_dapm_hp ||
				p->sink->id == snd_soc_dapm_line ||
				p->sink->id == snd_soc_dapm_input) {
2570
					ep = 0;
2571 2572 2573 2574 2575
					break;
			}
		}
		break;
	case snd_soc_dapm_line:
2576 2577 2578 2579 2580
		ep = 0;
		snd_soc_dapm_for_each_direction(dir) {
			if (!list_empty(&w->edges[dir]))
				ep |= SND_SOC_DAPM_DIR_TO_EP(dir);
		}
2581 2582
		break;
	default:
2583
		return;
2584
	}
2585 2586

	w->is_ep = ep;
2587 2588
}

2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632
static int snd_soc_dapm_check_dynamic_path(struct snd_soc_dapm_context *dapm,
	struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink,
	const char *control)
{
	bool dynamic_source = false;
	bool dynamic_sink = false;

	if (!control)
		return 0;

	switch (source->id) {
	case snd_soc_dapm_demux:
		dynamic_source = true;
		break;
	default:
		break;
	}

	switch (sink->id) {
	case snd_soc_dapm_mux:
	case snd_soc_dapm_switch:
	case snd_soc_dapm_mixer:
	case snd_soc_dapm_mixer_named_ctl:
		dynamic_sink = true;
		break;
	default:
		break;
	}

	if (dynamic_source && dynamic_sink) {
		dev_err(dapm->dev,
			"Direct connection between demux and mixer/mux not supported for path %s -> [%s] -> %s\n",
			source->name, control, sink->name);
		return -EINVAL;
	} else if (!dynamic_source && !dynamic_sink) {
		dev_err(dapm->dev,
			"Control not supported for path %s -> [%s] -> %s\n",
			source->name, control, sink->name);
		return -EINVAL;
	}

	return 0;
}

2633 2634 2635 2636 2637
static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
	struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
	const char *control,
	int (*connected)(struct snd_soc_dapm_widget *source,
			 struct snd_soc_dapm_widget *sink))
2638
{
2639 2640
	struct snd_soc_dapm_widget *widgets[2];
	enum snd_soc_dapm_direction dir;
2641
	struct snd_soc_dapm_path *path;
2642
	int ret;
2643

2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664
	if (wsink->is_supply && !wsource->is_supply) {
		dev_err(dapm->dev,
			"Connecting non-supply widget to supply widget is not supported (%s -> %s)\n",
			wsource->name, wsink->name);
		return -EINVAL;
	}

	if (connected && !wsource->is_supply) {
		dev_err(dapm->dev,
			"connected() callback only supported for supply widgets (%s -> %s)\n",
			wsource->name, wsink->name);
		return -EINVAL;
	}

	if (wsource->is_supply && control) {
		dev_err(dapm->dev,
			"Conditional paths are not supported for supply widgets (%s -> [%s] -> %s)\n",
			wsource->name, control, wsink->name);
		return -EINVAL;
	}

2665 2666 2667 2668
	ret = snd_soc_dapm_check_dynamic_path(dapm, wsource, wsink, control);
	if (ret)
		return ret;

2669 2670 2671 2672
	path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
	if (!path)
		return -ENOMEM;

2673 2674 2675 2676 2677
	path->node[SND_SOC_DAPM_DIR_IN] = wsource;
	path->node[SND_SOC_DAPM_DIR_OUT] = wsink;
	widgets[SND_SOC_DAPM_DIR_IN] = wsource;
	widgets[SND_SOC_DAPM_DIR_OUT] = wsink;

2678
	path->connected = connected;
2679
	INIT_LIST_HEAD(&path->list);
2680
	INIT_LIST_HEAD(&path->list_kcontrol);
2681

2682 2683 2684
	if (wsource->is_supply || wsink->is_supply)
		path->is_supply = 1;

2685 2686 2687
	/* connect static paths */
	if (control == NULL) {
		path->connect = 1;
2688
	} else {
2689 2690 2691 2692 2693 2694 2695 2696 2697 2698
		switch (wsource->id) {
		case snd_soc_dapm_demux:
			ret = dapm_connect_mux(dapm, path, control, wsource);
			if (ret)
				goto err;
			break;
		default:
			break;
		}

2699 2700
		switch (wsink->id) {
		case snd_soc_dapm_mux:
2701
			ret = dapm_connect_mux(dapm, path, control, wsink);
2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712
			if (ret != 0)
				goto err;
			break;
		case snd_soc_dapm_switch:
		case snd_soc_dapm_mixer:
		case snd_soc_dapm_mixer_named_ctl:
			ret = dapm_connect_mixer(dapm, path, control);
			if (ret != 0)
				goto err;
			break;
		default:
2713
			break;
2714
		}
2715
	}
2716

2717
	list_add(&path->list, &dapm->card->paths);
2718 2719
	snd_soc_dapm_for_each_direction(dir)
		list_add(&path->list_node[dir], &widgets[dir]->edges[dir]);
2720

2721 2722 2723 2724
	snd_soc_dapm_for_each_direction(dir) {
		dapm_update_widget_flags(widgets[dir]);
		dapm_mark_dirty(widgets[dir], "Route added");
	}
2725

2726 2727 2728
	if (dapm->card->instantiated && path->connect)
		dapm_path_invalidate(path);

2729
	return 0;
2730 2731 2732 2733
err:
	kfree(path);
	return ret;
}
2734

2735
static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2736
				  const struct snd_soc_dapm_route *route)
2737 2738 2739 2740 2741 2742 2743
{
	struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
	struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
	const char *sink;
	const char *source;
	char prefixed_sink[80];
	char prefixed_source[80];
2744
	const char *prefix;
2745 2746
	int ret;

2747 2748
	prefix = soc_dapm_prefix(dapm);
	if (prefix) {
2749
		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2750
			 prefix, route->sink);
2751 2752
		sink = prefixed_sink;
		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
2753
			 prefix, route->source);
2754 2755 2756 2757 2758 2759
		source = prefixed_source;
	} else {
		sink = route->sink;
		source = route->source;
	}

2760 2761 2762 2763 2764 2765
	wsource = dapm_wcache_lookup(&dapm->path_source_cache, source);
	wsink = dapm_wcache_lookup(&dapm->path_sink_cache, sink);

	if (wsink && wsource)
		goto skip_search;

2766 2767 2768 2769 2770 2771 2772
	/*
	 * find src and dest widgets over all widgets but favor a widget from
	 * current DAPM context
	 */
	list_for_each_entry(w, &dapm->card->widgets, list) {
		if (!wsink && !(strcmp(w->name, sink))) {
			wtsink = w;
2773
			if (w->dapm == dapm) {
2774
				wsink = w;
2775 2776 2777
				if (wsource)
					break;
			}
2778 2779 2780 2781
			continue;
		}
		if (!wsource && !(strcmp(w->name, source))) {
			wtsource = w;
2782
			if (w->dapm == dapm) {
2783
				wsource = w;
2784 2785 2786
				if (wsink)
					break;
			}
2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805
		}
	}
	/* use widget from another DAPM context if not found from this */
	if (!wsink)
		wsink = wtsink;
	if (!wsource)
		wsource = wtsource;

	if (wsource == NULL) {
		dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
			route->source);
		return -ENODEV;
	}
	if (wsink == NULL) {
		dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
			route->sink);
		return -ENODEV;
	}

2806 2807 2808 2809
skip_search:
	dapm_wcache_update(&dapm->path_sink_cache, wsink);
	dapm_wcache_update(&dapm->path_source_cache, wsource);

2810 2811 2812 2813 2814 2815
	ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control,
		route->connected);
	if (ret)
		goto err;

	return 0;
2816
err:
2817
	dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n",
2818
		 source, route->control, sink);
2819 2820
	return ret;
}
2821

2822 2823 2824
static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
				  const struct snd_soc_dapm_route *route)
{
2825
	struct snd_soc_dapm_widget *wsource, *wsink;
2826 2827 2828 2829 2830
	struct snd_soc_dapm_path *path, *p;
	const char *sink;
	const char *source;
	char prefixed_sink[80];
	char prefixed_source[80];
2831
	const char *prefix;
2832 2833 2834

	if (route->control) {
		dev_err(dapm->dev,
2835
			"ASoC: Removal of routes with controls not supported\n");
2836 2837 2838
		return -EINVAL;
	}

2839 2840
	prefix = soc_dapm_prefix(dapm);
	if (prefix) {
2841
		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2842
			 prefix, route->sink);
2843 2844
		sink = prefixed_sink;
		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
2845
			 prefix, route->source);
2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862
		source = prefixed_source;
	} else {
		sink = route->sink;
		source = route->source;
	}

	path = NULL;
	list_for_each_entry(p, &dapm->card->paths, list) {
		if (strcmp(p->source->name, source) != 0)
			continue;
		if (strcmp(p->sink->name, sink) != 0)
			continue;
		path = p;
		break;
	}

	if (path) {
2863 2864 2865 2866 2867
		wsource = path->source;
		wsink = path->sink;

		dapm_mark_dirty(wsource, "Route removed");
		dapm_mark_dirty(wsink, "Route removed");
2868 2869
		if (path->connect)
			dapm_path_invalidate(path);
2870

2871
		dapm_free_path(path);
2872 2873 2874 2875

		/* Update any path related flags */
		dapm_update_widget_flags(wsource);
		dapm_update_widget_flags(wsink);
2876
	} else {
2877
		dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n",
2878 2879 2880 2881 2882 2883
			 source, sink);
	}

	return 0;
}

2884 2885
/**
 * snd_soc_dapm_add_routes - Add routes between DAPM widgets
L
Liam Girdwood 已提交
2886
 * @dapm: DAPM context
2887 2888 2889 2890 2891 2892 2893 2894 2895 2896
 * @route: audio routes
 * @num: number of routes
 *
 * Connects 2 dapm widgets together via a named audio path. The sink is
 * the widget receiving the audio signal, whilst the source is the sender
 * of the audio signal.
 *
 * Returns 0 for success else error. On error all resources can be freed
 * with a call to snd_soc_card_free().
 */
L
Liam Girdwood 已提交
2897
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
2898 2899
			    const struct snd_soc_dapm_route *route, int num)
{
2900
	int i, r, ret = 0;
2901

2902
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2903
	for (i = 0; i < num; i++) {
2904
		r = snd_soc_dapm_add_route(dapm, route);
2905
		if (r < 0) {
2906 2907 2908 2909
			dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n",
				route->source,
				route->control ? route->control : "direct",
				route->sink);
2910
			ret = r;
2911 2912 2913
		}
		route++;
	}
2914
	mutex_unlock(&dapm->card->dapm_mutex);
2915

2916
	return ret;
2917 2918 2919
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);

2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930
/**
 * snd_soc_dapm_del_routes - Remove routes between DAPM widgets
 * @dapm: DAPM context
 * @route: audio routes
 * @num: number of routes
 *
 * Removes routes from the DAPM context.
 */
int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
			    const struct snd_soc_dapm_route *route, int num)
{
2931
	int i;
2932

2933
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2934 2935 2936 2937 2938 2939
	for (i = 0; i < num; i++) {
		snd_soc_dapm_del_route(dapm, route);
		route++;
	}
	mutex_unlock(&dapm->card->dapm_mutex);

2940
	return 0;
2941 2942 2943
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_del_routes);

2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956
static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
				   const struct snd_soc_dapm_route *route)
{
	struct snd_soc_dapm_widget *source = dapm_find_widget(dapm,
							      route->source,
							      true);
	struct snd_soc_dapm_widget *sink = dapm_find_widget(dapm,
							    route->sink,
							    true);
	struct snd_soc_dapm_path *path;
	int count = 0;

	if (!source) {
2957
		dev_err(dapm->dev, "ASoC: Unable to find source %s for weak route\n",
2958 2959 2960 2961 2962
			route->source);
		return -ENODEV;
	}

	if (!sink) {
2963
		dev_err(dapm->dev, "ASoC: Unable to find sink %s for weak route\n",
2964 2965 2966 2967 2968
			route->sink);
		return -ENODEV;
	}

	if (route->control || route->connected)
2969
		dev_warn(dapm->dev, "ASoC: Ignoring control for weak route %s->%s\n",
2970 2971
			 route->source, route->sink);

2972
	snd_soc_dapm_widget_for_each_sink_path(source, path) {
2973 2974 2975 2976 2977 2978 2979
		if (path->sink == sink) {
			path->weak = 1;
			count++;
		}
	}

	if (count == 0)
2980
		dev_err(dapm->dev, "ASoC: No path found for weak route %s->%s\n",
2981 2982
			route->source, route->sink);
	if (count > 1)
2983
		dev_warn(dapm->dev, "ASoC: %d paths found for weak route %s->%s\n",
2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010
			 count, route->source, route->sink);

	return 0;
}

/**
 * snd_soc_dapm_weak_routes - Mark routes between DAPM widgets as weak
 * @dapm: DAPM context
 * @route: audio routes
 * @num: number of routes
 *
 * Mark existing routes matching those specified in the passed array
 * as being weak, meaning that they are ignored for the purpose of
 * power decisions.  The main intended use case is for sidetone paths
 * which couple audio between other independent paths if they are both
 * active in order to make the combination work better at the user
 * level but which aren't intended to be "used".
 *
 * Note that CODEC drivers should not use this as sidetone type paths
 * can frequently also be used as bypass paths.
 */
int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
			     const struct snd_soc_dapm_route *route, int num)
{
	int i, err;
	int ret = 0;

3011
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
3012 3013 3014 3015 3016 3017
	for (i = 0; i < num; i++) {
		err = snd_soc_dapm_weak_route(dapm, route);
		if (err)
			ret = err;
		route++;
	}
3018
	mutex_unlock(&dapm->card->dapm_mutex);
3019 3020 3021 3022 3023

	return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);

3024 3025
/**
 * snd_soc_dapm_new_widgets - add new dapm widgets
3026
 * @card: card to be checked for new dapm widgets
3027 3028 3029 3030 3031
 *
 * Checks the codec for any new dapm widgets and creates them if found.
 *
 * Returns 0 for success.
 */
3032
int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
3033 3034
{
	struct snd_soc_dapm_widget *w;
3035
	unsigned int val;
3036

3037
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
3038

3039
	list_for_each_entry(w, &card->widgets, list)
3040 3041 3042 3043
	{
		if (w->new)
			continue;

3044
		if (w->num_kcontrols) {
K
Kees Cook 已提交
3045
			w->kcontrols = kcalloc(w->num_kcontrols,
3046 3047
						sizeof(struct snd_kcontrol *),
						GFP_KERNEL);
3048
			if (!w->kcontrols) {
3049
				mutex_unlock(&card->dapm_mutex);
3050
				return -ENOMEM;
3051
			}
3052 3053
		}

3054 3055 3056
		switch(w->id) {
		case snd_soc_dapm_switch:
		case snd_soc_dapm_mixer:
3057
		case snd_soc_dapm_mixer_named_ctl:
3058
			dapm_new_mixer(w);
3059 3060
			break;
		case snd_soc_dapm_mux:
3061
		case snd_soc_dapm_demux:
3062
			dapm_new_mux(w);
3063 3064
			break;
		case snd_soc_dapm_pga:
3065
		case snd_soc_dapm_out_drv:
3066
			dapm_new_pga(w);
3067
			break;
3068 3069 3070
		case snd_soc_dapm_dai_link:
			dapm_new_dai_link(w);
			break;
3071
		default:
3072 3073
			break;
		}
3074 3075 3076

		/* Read the initial power state from the device */
		if (w->reg >= 0) {
3077
			soc_dapm_read(w->dapm, w->reg, &val);
3078
			val = val >> w->shift;
3079 3080
			val &= w->mask;
			if (val == w->on_val)
3081 3082 3083
				w->power = 1;
		}

3084
		w->new = 1;
3085

3086
		dapm_mark_dirty(w, "new widget");
3087
		dapm_debugfs_add_widget(w);
3088 3089
	}

3090 3091
	dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
	mutex_unlock(&card->dapm_mutex);
3092 3093 3094 3095 3096 3097 3098
	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);

/**
 * snd_soc_dapm_get_volsw - dapm mixer get callback
 * @kcontrol: mixer control
M
Mark Brown 已提交
3099
 * @ucontrol: control element information
3100 3101 3102 3103 3104 3105 3106 3107
 *
 * Callback to get the value of a dapm mixer control.
 *
 * Returns 0 for success.
 */
int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
3108 3109
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
	struct snd_soc_card *card = dapm->card;
3110 3111
	struct soc_mixer_control *mc =
		(struct soc_mixer_control *)kcontrol->private_value;
3112
	int reg = mc->reg;
3113
	unsigned int shift = mc->shift;
3114
	int max = mc->max;
3115
	unsigned int width = fls(max);
3116
	unsigned int mask = (1 << fls(max)) - 1;
3117
	unsigned int invert = mc->invert;
3118
	unsigned int reg_val, val, rval = 0;
3119
	int ret = 0;
3120

3121
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3122
	if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) {
3123 3124 3125 3126 3127 3128 3129 3130
		ret = soc_dapm_read(dapm, reg, &reg_val);
		val = (reg_val >> shift) & mask;

		if (ret == 0 && reg != mc->rreg)
			ret = soc_dapm_read(dapm, mc->rreg, &reg_val);

		if (snd_soc_volsw_is_stereo(mc))
			rval = (reg_val >> mc->rshift) & mask;
3131
	} else {
3132 3133 3134 3135 3136
		reg_val = dapm_kcontrol_get_value(kcontrol);
		val = reg_val & mask;

		if (snd_soc_volsw_is_stereo(mc))
			rval = (reg_val >> width) & mask;
3137
	}
3138 3139
	mutex_unlock(&card->dapm_mutex);

3140 3141 3142
	if (ret)
		return ret;

3143
	if (invert)
3144 3145 3146
		ucontrol->value.integer.value[0] = max - val;
	else
		ucontrol->value.integer.value[0] = val;
3147

3148 3149 3150 3151 3152 3153 3154
	if (snd_soc_volsw_is_stereo(mc)) {
		if (invert)
			ucontrol->value.integer.value[1] = max - rval;
		else
			ucontrol->value.integer.value[1] = rval;
	}

3155
	return ret;
3156 3157 3158 3159 3160 3161
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);

/**
 * snd_soc_dapm_put_volsw - dapm mixer set callback
 * @kcontrol: mixer control
M
Mark Brown 已提交
3162
 * @ucontrol: control element information
3163 3164 3165 3166 3167 3168 3169 3170
 *
 * Callback to set the value of a dapm mixer control.
 *
 * Returns 0 for success.
 */
int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
3171 3172
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
	struct snd_soc_card *card = dapm->card;
3173 3174
	struct soc_mixer_control *mc =
		(struct soc_mixer_control *)kcontrol->private_value;
3175
	int reg = mc->reg;
3176
	unsigned int shift = mc->shift;
3177
	int max = mc->max;
3178 3179
	unsigned int width = fls(max);
	unsigned int mask = (1 << width) - 1;
3180
	unsigned int invert = mc->invert;
3181 3182
	unsigned int val, rval = 0;
	int connect, rconnect = -1, change, reg_change = 0;
3183
	struct snd_soc_dapm_update update = {};
3184
	int ret = 0;
3185 3186

	val = (ucontrol->value.integer.value[0] & mask);
3187
	connect = !!val;
3188 3189

	if (invert)
P
Philipp Zabel 已提交
3190
		val = max - val;
3191

3192 3193 3194 3195 3196 3197 3198
	if (snd_soc_volsw_is_stereo(mc)) {
		rval = (ucontrol->value.integer.value[1] & mask);
		rconnect = !!rval;
		if (invert)
			rval = max - rval;
	}

3199
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3200

3201 3202 3203 3204 3205 3206
	/* This assumes field width < (bits in unsigned int / 2) */
	if (width > sizeof(unsigned int) * 8 / 2)
		dev_warn(dapm->dev,
			 "ASoC: control %s field width limit exceeded\n",
			 kcontrol->id.name);
	change = dapm_kcontrol_set_value(kcontrol, val | (rval << width));
3207

3208 3209
	if (reg != SND_SOC_NOPM) {
		val = val << shift;
3210 3211 3212
		rval = rval << mc->rshift;

		reg_change = soc_dapm_test_bits(dapm, reg, mask << shift, val);
3213

3214 3215 3216 3217
		if (snd_soc_volsw_is_stereo(mc))
			reg_change |= soc_dapm_test_bits(dapm, mc->rreg,
							 mask << mc->rshift,
							 rval);
3218 3219 3220 3221
	}

	if (change || reg_change) {
		if (reg_change) {
3222 3223 3224 3225 3226 3227
			if (snd_soc_volsw_is_stereo(mc)) {
				update.has_second_set = true;
				update.reg2 = mc->rreg;
				update.mask2 = mask << mc->rshift;
				update.val2 = rval;
			}
3228 3229
			update.kcontrol = kcontrol;
			update.reg = reg;
3230
			update.mask = mask << shift;
3231 3232
			update.val = val;
			card->update = &update;
3233
		}
3234
		change |= reg_change;
3235

3236 3237
		ret = soc_dapm_mixer_update_power(card, kcontrol, connect,
						  rconnect);
3238

3239
		card->update = NULL;
3240 3241
	}

3242
	mutex_unlock(&card->dapm_mutex);
3243 3244 3245 3246

	if (ret > 0)
		soc_dpcm_runtime_update(card);

3247
	return change;
3248 3249 3250 3251 3252 3253
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);

/**
 * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
 * @kcontrol: mixer control
M
Mark Brown 已提交
3254
 * @ucontrol: control element information
3255 3256 3257 3258 3259 3260 3261 3262
 *
 * Callback to get the value of a dapm enumerated double mixer control.
 *
 * Returns 0 for success.
 */
int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
3263
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
3264
	struct snd_soc_card *card = dapm->card;
3265
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
3266
	unsigned int reg_val, val;
3267

3268 3269
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
	if (e->reg != SND_SOC_NOPM && dapm_kcontrol_is_powered(kcontrol)) {
3270
		int ret = soc_dapm_read(dapm, e->reg, &reg_val);
3271 3272
		if (ret) {
			mutex_unlock(&card->dapm_mutex);
3273
			return ret;
3274
		}
3275
	} else {
3276
		reg_val = dapm_kcontrol_get_value(kcontrol);
3277
	}
3278
	mutex_unlock(&card->dapm_mutex);
P
Peter Ujfalusi 已提交
3279 3280

	val = (reg_val >> e->shift_l) & e->mask;
3281
	ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val);
P
Peter Ujfalusi 已提交
3282 3283
	if (e->shift_l != e->shift_r) {
		val = (reg_val >> e->shift_r) & e->mask;
3284 3285
		val = snd_soc_enum_val_to_item(e, val);
		ucontrol->value.enumerated.item[1] = val;
P
Peter Ujfalusi 已提交
3286 3287
	}

3288
	return 0;
P
Peter Ujfalusi 已提交
3289
}
3290
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
P
Peter Ujfalusi 已提交
3291 3292

/**
3293
 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
P
Peter Ujfalusi 已提交
3294 3295 3296
 * @kcontrol: mixer control
 * @ucontrol: control element information
 *
3297
 * Callback to set the value of a dapm enumerated double mixer control.
P
Peter Ujfalusi 已提交
3298 3299 3300
 *
 * Returns 0 for success.
 */
3301
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
P
Peter Ujfalusi 已提交
3302 3303
	struct snd_ctl_elem_value *ucontrol)
{
3304 3305
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
	struct snd_soc_card *card = dapm->card;
3306
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
3307
	unsigned int *item = ucontrol->value.enumerated.item;
3308
	unsigned int val, change, reg_change = 0;
3309
	unsigned int mask;
3310
	struct snd_soc_dapm_update update = {};
3311
	int ret = 0;
P
Peter Ujfalusi 已提交
3312

3313
	if (item[0] >= e->items)
P
Peter Ujfalusi 已提交
3314
		return -EINVAL;
3315 3316

	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
P
Peter Ujfalusi 已提交
3317 3318
	mask = e->mask << e->shift_l;
	if (e->shift_l != e->shift_r) {
3319
		if (item[1] > e->items)
P
Peter Ujfalusi 已提交
3320
			return -EINVAL;
3321
		val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
P
Peter Ujfalusi 已提交
3322 3323 3324
		mask |= e->mask << e->shift_r;
	}

3325
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3326

3327 3328
	change = dapm_kcontrol_set_value(kcontrol, val);

3329
	if (e->reg != SND_SOC_NOPM)
3330
		reg_change = soc_dapm_test_bits(dapm, e->reg, mask, val);
3331

3332 3333
	if (change || reg_change) {
		if (reg_change) {
3334 3335 3336 3337 3338 3339
			update.kcontrol = kcontrol;
			update.reg = e->reg;
			update.mask = mask;
			update.val = val;
			card->update = &update;
		}
3340
		change |= reg_change;
3341

3342
		ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e);
3343

3344
		card->update = NULL;
3345
	}
P
Peter Ujfalusi 已提交
3346

3347
	mutex_unlock(&card->dapm_mutex);
3348 3349 3350 3351

	if (ret > 0)
		soc_dpcm_runtime_update(card);

3352
	return change;
P
Peter Ujfalusi 已提交
3353
}
3354
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
P
Peter Ujfalusi 已提交
3355

3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384
/**
 * snd_soc_dapm_info_pin_switch - Info for a pin switch
 *
 * @kcontrol: mixer control
 * @uinfo: control element information
 *
 * Callback to provide information about a pin switch control.
 */
int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 1;

	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);

/**
 * snd_soc_dapm_get_pin_switch - Get information for a pin switch
 *
 * @kcontrol: mixer control
 * @ucontrol: Value
 */
int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
3385
	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3386 3387
	const char *pin = (const char *)kcontrol->private_value;

3388
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3389 3390

	ucontrol->value.integer.value[0] =
3391
		snd_soc_dapm_get_pin_status(&card->dapm, pin);
3392

3393
	mutex_unlock(&card->dapm_mutex);
3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407

	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);

/**
 * snd_soc_dapm_put_pin_switch - Set information for a pin switch
 *
 * @kcontrol: mixer control
 * @ucontrol: Value
 */
int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
3408
	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3409 3410 3411
	const char *pin = (const char *)kcontrol->private_value;

	if (ucontrol->value.integer.value[0])
3412
		snd_soc_dapm_enable_pin(&card->dapm, pin);
3413
	else
3414
		snd_soc_dapm_disable_pin(&card->dapm, pin);
3415

3416
	snd_soc_dapm_sync(&card->dapm);
3417 3418 3419 3420
	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);

3421 3422
struct snd_soc_dapm_widget *
snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
3423
			 const struct snd_soc_dapm_widget *widget)
3424
{
3425
	enum snd_soc_dapm_direction dir;
3426
	struct snd_soc_dapm_widget *w;
3427
	const char *prefix;
3428
	int ret;
3429 3430

	if ((w = dapm_cnew_widget(widget)) == NULL)
3431
		return ERR_PTR(-ENOMEM);
3432

3433 3434
	switch (w->id) {
	case snd_soc_dapm_regulator_supply:
3435 3436 3437
		w->regulator = devm_regulator_get(dapm->dev, w->name);
		if (IS_ERR(w->regulator)) {
			ret = PTR_ERR(w->regulator);
3438
			goto request_failed;
3439
		}
3440

3441
		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
3442 3443
			ret = regulator_allow_bypass(w->regulator, true);
			if (ret != 0)
3444
				dev_warn(dapm->dev,
3445
					 "ASoC: Failed to bypass %s: %d\n",
3446 3447
					 w->name, ret);
		}
3448
		break;
3449 3450
	case snd_soc_dapm_pinctrl:
		w->pinctrl = devm_pinctrl_get(dapm->dev);
3451
		if (IS_ERR(w->pinctrl)) {
3452
			ret = PTR_ERR(w->pinctrl);
3453
			goto request_failed;
3454 3455
		}
		break;
3456
	case snd_soc_dapm_clock_supply:
M
Mark Brown 已提交
3457
		w->clk = devm_clk_get(dapm->dev, w->name);
3458 3459
		if (IS_ERR(w->clk)) {
			ret = PTR_ERR(w->clk);
3460
			goto request_failed;
3461 3462
		}
		break;
3463 3464 3465
	default:
		break;
	}
3466

3467
	prefix = soc_dapm_prefix(dapm);
3468
	if (prefix)
3469
		w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name);
3470
	else
3471
		w->name = kstrdup_const(widget->name, GFP_KERNEL);
3472 3473
	if (w->name == NULL) {
		kfree(w);
3474
		return ERR_PTR(-ENOMEM);
3475 3476
	}

3477
	switch (w->id) {
3478
	case snd_soc_dapm_mic:
3479
		w->is_ep = SND_SOC_DAPM_EP_SOURCE;
3480 3481
		w->power_check = dapm_generic_check_power;
		break;
3482 3483
	case snd_soc_dapm_input:
		if (!dapm->card->fully_routed)
3484
			w->is_ep = SND_SOC_DAPM_EP_SOURCE;
3485 3486
		w->power_check = dapm_generic_check_power;
		break;
3487 3488
	case snd_soc_dapm_spk:
	case snd_soc_dapm_hp:
3489
		w->is_ep = SND_SOC_DAPM_EP_SINK;
3490 3491
		w->power_check = dapm_generic_check_power;
		break;
3492 3493
	case snd_soc_dapm_output:
		if (!dapm->card->fully_routed)
3494
			w->is_ep = SND_SOC_DAPM_EP_SINK;
3495 3496
		w->power_check = dapm_generic_check_power;
		break;
3497 3498
	case snd_soc_dapm_vmid:
	case snd_soc_dapm_siggen:
3499
		w->is_ep = SND_SOC_DAPM_EP_SOURCE;
3500 3501
		w->power_check = dapm_always_on_check_power;
		break;
V
Vinod Koul 已提交
3502 3503 3504 3505 3506
	case snd_soc_dapm_sink:
		w->is_ep = SND_SOC_DAPM_EP_SINK;
		w->power_check = dapm_always_on_check_power;
		break;

3507
	case snd_soc_dapm_mux:
3508
	case snd_soc_dapm_demux:
3509 3510 3511
	case snd_soc_dapm_switch:
	case snd_soc_dapm_mixer:
	case snd_soc_dapm_mixer_named_ctl:
3512 3513 3514 3515
	case snd_soc_dapm_adc:
	case snd_soc_dapm_aif_out:
	case snd_soc_dapm_dac:
	case snd_soc_dapm_aif_in:
3516 3517 3518 3519
	case snd_soc_dapm_pga:
	case snd_soc_dapm_out_drv:
	case snd_soc_dapm_micbias:
	case snd_soc_dapm_line:
3520
	case snd_soc_dapm_dai_link:
3521 3522
	case snd_soc_dapm_dai_out:
	case snd_soc_dapm_dai_in:
3523 3524 3525
		w->power_check = dapm_generic_check_power;
		break;
	case snd_soc_dapm_supply:
3526
	case snd_soc_dapm_regulator_supply:
3527
	case snd_soc_dapm_pinctrl:
3528
	case snd_soc_dapm_clock_supply:
3529
	case snd_soc_dapm_kcontrol:
3530
		w->is_supply = 1;
3531 3532 3533 3534 3535 3536 3537
		w->power_check = dapm_supply_check_power;
		break;
	default:
		w->power_check = dapm_always_on_check_power;
		break;
	}

L
Liam Girdwood 已提交
3538
	w->dapm = dapm;
3539
	INIT_LIST_HEAD(&w->list);
3540
	INIT_LIST_HEAD(&w->dirty);
3541
	list_add_tail(&w->list, &dapm->card->widgets);
3542

3543 3544 3545 3546
	snd_soc_dapm_for_each_direction(dir) {
		INIT_LIST_HEAD(&w->edges[dir]);
		w->endpoints[dir] = -1;
	}
3547

3548
	/* machine layer sets up unconnected pins and insertions */
3549
	w->connected = 1;
3550
	return w;
3551 3552 3553 3554 3555 3556 3557

request_failed:
	if (ret != -EPROBE_DEFER)
		dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
			w->name, ret);

	return ERR_PTR(ret);
3558 3559
}

3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582
/**
 * snd_soc_dapm_new_control - create new dapm control
 * @dapm: DAPM context
 * @widget: widget template
 *
 * Creates new DAPM control based upon a template.
 *
 * Returns a widget pointer on success or an error pointer on failure
 */
struct snd_soc_dapm_widget *
snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
			 const struct snd_soc_dapm_widget *widget)
{
	struct snd_soc_dapm_widget *w;

	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
	w = snd_soc_dapm_new_control_unlocked(dapm, widget);
	mutex_unlock(&dapm->card->dapm_mutex);

	return w;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);

3583 3584
/**
 * snd_soc_dapm_new_controls - create new dapm controls
L
Liam Girdwood 已提交
3585
 * @dapm: DAPM context
3586 3587 3588 3589 3590 3591 3592
 * @widget: widget array
 * @num: number of widgets
 *
 * Creates new DAPM controls based upon the templates.
 *
 * Returns 0 for success else error.
 */
L
Liam Girdwood 已提交
3593
int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
3594 3595 3596
	const struct snd_soc_dapm_widget *widget,
	int num)
{
3597 3598
	struct snd_soc_dapm_widget *w;
	int i;
3599
	int ret = 0;
3600

3601
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
3602
	for (i = 0; i < num; i++) {
3603
		w = snd_soc_dapm_new_control_unlocked(dapm, widget);
3604 3605
		if (IS_ERR(w)) {
			ret = PTR_ERR(w);
3606
			break;
3607
		}
3608 3609
		widget++;
	}
3610
	mutex_unlock(&dapm->card->dapm_mutex);
3611
	return ret;
3612 3613 3614
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);

3615 3616 3617
static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
				  struct snd_kcontrol *kcontrol, int event)
{
3618
	struct snd_soc_dapm_path *path;
3619
	struct snd_soc_dai *source, *sink;
3620
	struct snd_soc_pcm_runtime *rtd = w->priv;
3621
	const struct snd_soc_pcm_stream *config;
3622
	struct snd_pcm_substream substream;
3623
	struct snd_pcm_hw_params *params = NULL;
3624
	struct snd_pcm_runtime *runtime = NULL;
3625
	unsigned int fmt;
3626 3627
	int ret;

3628 3629
	config = rtd->dai_link->params + rtd->params_select;

3630
	if (WARN_ON(!config) ||
3631 3632
	    WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) ||
		    list_empty(&w->edges[SND_SOC_DAPM_DIR_IN])))
3633
		return -EINVAL;
3634 3635 3636 3637 3638

	/* Be a little careful as we don't want to overflow the mask array */
	if (config->formats) {
		fmt = ffs(config->formats) - 1;
	} else {
3639
		dev_warn(w->dapm->dev, "ASoC: Invalid format %llx specified\n",
3640 3641 3642 3643 3644
			 config->formats);
		fmt = 0;
	}

	/* Currently very limited parameter selection */
3645 3646 3647 3648 3649 3650
	params = kzalloc(sizeof(*params), GFP_KERNEL);
	if (!params) {
		ret = -ENOMEM;
		goto out;
	}
	snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt);
3651

3652
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min =
3653
		config->rate_min;
3654
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max =
3655 3656
		config->rate_max;

3657
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min
3658
		= config->channels_min;
3659
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max
3660 3661 3662 3663
		= config->channels_max;

	memset(&substream, 0, sizeof(substream));

3664 3665 3666 3667 3668 3669 3670
	/* Allocate a dummy snd_pcm_runtime for startup() and other ops() */
	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
	if (!runtime) {
		ret = -ENOMEM;
		goto out;
	}
	substream.runtime = runtime;
3671
	substream.private_data = rtd;
3672

3673 3674
	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
3675
		substream.stream = SNDRV_PCM_STREAM_CAPTURE;
3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688
		snd_soc_dapm_widget_for_each_source_path(w, path) {
			source = path->source->priv;

			if (source->driver->ops->startup) {
				ret = source->driver->ops->startup(&substream,
								   source);
				if (ret < 0) {
					dev_err(source->dev,
						"ASoC: startup() failed: %d\n",
						ret);
					goto out;
				}
				source->active++;
3689
			}
3690 3691 3692
			ret = soc_dai_hw_params(&substream, params, source);
			if (ret < 0)
				goto out;
3693
		}
3694

3695
		substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708
		snd_soc_dapm_widget_for_each_sink_path(w, path) {
			sink = path->sink->priv;

			if (sink->driver->ops->startup) {
				ret = sink->driver->ops->startup(&substream,
								 sink);
				if (ret < 0) {
					dev_err(sink->dev,
						"ASoC: startup() failed: %d\n",
						ret);
					goto out;
				}
				sink->active++;
3709
			}
3710 3711 3712
			ret = soc_dai_hw_params(&substream, params, sink);
			if (ret < 0)
				goto out;
3713
		}
3714 3715 3716
		break;

	case SND_SOC_DAPM_POST_PMU:
3717 3718 3719 3720 3721 3722 3723 3724 3725 3726
		snd_soc_dapm_widget_for_each_sink_path(w, path) {
			sink = path->sink->priv;

			ret = snd_soc_dai_digital_mute(sink, 0,
						       SNDRV_PCM_STREAM_PLAYBACK);
			if (ret != 0 && ret != -ENOTSUPP)
				dev_warn(sink->dev,
					 "ASoC: Failed to unmute: %d\n", ret);
			ret = 0;
		}
3727 3728 3729
		break;

	case SND_SOC_DAPM_PRE_PMD:
3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742
		snd_soc_dapm_widget_for_each_sink_path(w, path) {
			sink = path->sink->priv;

			ret = snd_soc_dai_digital_mute(sink, 1,
						       SNDRV_PCM_STREAM_PLAYBACK);
			if (ret != 0 && ret != -ENOTSUPP)
				dev_warn(sink->dev,
					 "ASoC: Failed to mute: %d\n", ret);
			ret = 0;
		}

		snd_soc_dapm_widget_for_each_source_path(w, path) {
			source = path->source->priv;
3743

3744 3745 3746 3747 3748 3749
			source->active--;
			if (source->driver->ops->shutdown) {
				substream.stream = SNDRV_PCM_STREAM_CAPTURE;
				source->driver->ops->shutdown(&substream,
							      source);
			}
3750 3751
		}

3752 3753 3754 3755 3756 3757 3758 3759
		snd_soc_dapm_widget_for_each_sink_path(w, path) {
			sink = path->sink->priv;

			sink->active--;
			if (sink->driver->ops->shutdown) {
				substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
				sink->driver->ops->shutdown(&substream, sink);
			}
3760
		}
3761 3762 3763
		break;

	default:
T
Takashi Iwai 已提交
3764
		WARN(1, "Unknown event %d\n", event);
S
Sudip Mukherjee 已提交
3765
		ret = -EINVAL;
3766 3767
	}

3768
out:
3769
	kfree(runtime);
3770 3771
	kfree(params);
	return ret;
3772 3773
}

3774 3775 3776 3777
static int snd_soc_dapm_dai_link_get(struct snd_kcontrol *kcontrol,
			  struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
3778
	struct snd_soc_pcm_runtime *rtd = w->priv;
3779

3780
	ucontrol->value.enumerated.item[0] = rtd->params_select;
3781 3782 3783 3784 3785 3786 3787 3788

	return 0;
}

static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol,
			  struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
3789
	struct snd_soc_pcm_runtime *rtd = w->priv;
3790 3791 3792 3793 3794

	/* Can't change the config when widget is already powered */
	if (w->power)
		return -EBUSY;

3795
	if (ucontrol->value.enumerated.item[0] == rtd->params_select)
3796 3797
		return 0;

3798
	if (ucontrol->value.enumerated.item[0] >= rtd->dai_link->num_params)
3799 3800
		return -EINVAL;

3801
	rtd->params_select = ucontrol->value.enumerated.item[0];
3802 3803 3804 3805

	return 0;
}

3806
static void
3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825
snd_soc_dapm_free_kcontrol(struct snd_soc_card *card,
			unsigned long *private_value,
			int num_params,
			const char **w_param_text)
{
	int count;

	devm_kfree(card->dev, (void *)*private_value);
	for (count = 0 ; count < num_params; count++)
		devm_kfree(card->dev, (void *)w_param_text[count]);
	devm_kfree(card->dev, w_param_text);
}

static struct snd_kcontrol_new *
snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card,
			char *link_name,
			const struct snd_soc_pcm_stream *params,
			int num_params, const char **w_param_text,
			unsigned long *private_value)
3826
{
3827 3828 3829 3830 3831 3832 3833 3834
	struct soc_enum w_param_enum[] = {
		SOC_ENUM_SINGLE(0, 0, 0, NULL),
	};
	struct snd_kcontrol_new kcontrol_dai_link[] = {
		SOC_ENUM_EXT(NULL, w_param_enum[0],
			     snd_soc_dapm_dai_link_get,
			     snd_soc_dapm_dai_link_put),
	};
3835
	struct snd_kcontrol_new *kcontrol_news;
3836
	const struct snd_soc_pcm_stream *config = params;
3837
	int count;
3838

3839 3840 3841 3842 3843 3844
	for (count = 0 ; count < num_params; count++) {
		if (!config->stream_name) {
			dev_warn(card->dapm.dev,
				"ASoC: anonymous config %d for dai link %s\n",
				count, link_name);
			w_param_text[count] =
C
Charles Keepax 已提交
3845 3846 3847
				devm_kasprintf(card->dev, GFP_KERNEL,
					       "Anonymous Configuration %d",
					       count);
3848 3849 3850 3851 3852 3853
		} else {
			w_param_text[count] = devm_kmemdup(card->dev,
						config->stream_name,
						strlen(config->stream_name) + 1,
						GFP_KERNEL);
		}
3854 3855
		if (!w_param_text[count])
			goto outfree_w_param;
3856 3857
		config++;
	}
3858

3859 3860
	w_param_enum[0].items = num_params;
	w_param_enum[0].texts = w_param_text;
3861

3862
	*private_value =
3863 3864 3865
		(unsigned long) devm_kmemdup(card->dev,
			(void *)(kcontrol_dai_link[0].private_value),
			sizeof(struct soc_enum), GFP_KERNEL);
3866
	if (!*private_value) {
3867 3868
		dev_err(card->dev, "ASoC: Failed to create control for %s widget\n",
			link_name);
3869
		goto outfree_w_param;
3870
	}
3871
	kcontrol_dai_link[0].private_value = *private_value;
3872
	/* duplicate kcontrol_dai_link on heap so that memory persists */
3873
	kcontrol_news = devm_kmemdup(card->dev, &kcontrol_dai_link[0],
3874 3875
					sizeof(struct snd_kcontrol_new),
					GFP_KERNEL);
3876
	if (!kcontrol_news) {
3877 3878
		dev_err(card->dev, "ASoC: Failed to create control for %s widget\n",
			link_name);
3879
		goto outfree_w_param;
3880
	}
3881
	return kcontrol_news;
3882

3883 3884 3885 3886 3887
outfree_w_param:
	snd_soc_dapm_free_kcontrol(card, private_value, num_params, w_param_text);
	return NULL;
}

3888 3889 3890 3891
static struct snd_soc_dapm_widget *
snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd,
		     struct snd_soc_dapm_widget *source,
		     struct snd_soc_dapm_widget *sink)
3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902
{
	struct snd_soc_dapm_widget template;
	struct snd_soc_dapm_widget *w;
	const char **w_param_text;
	unsigned long private_value;
	char *link_name;
	int ret;

	link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s",
				   source->name, sink->name);
	if (!link_name)
3903
		return ERR_PTR(-ENOMEM);
3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914

	memset(&template, 0, sizeof(template));
	template.reg = SND_SOC_NOPM;
	template.id = snd_soc_dapm_dai_link;
	template.name = link_name;
	template.event = snd_soc_dai_link_event;
	template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
		SND_SOC_DAPM_PRE_PMD;
	template.kcontrol_news = NULL;

	/* allocate memory for control, only in case of multiple configs */
3915 3916 3917 3918
	if (rtd->dai_link->num_params > 1) {
		w_param_text = devm_kcalloc(card->dev,
					    rtd->dai_link->num_params,
					    sizeof(char *), GFP_KERNEL);
3919 3920 3921 3922
		if (!w_param_text) {
			ret = -ENOMEM;
			goto param_fail;
		}
3923

3924 3925 3926
		template.num_kcontrols = 1;
		template.kcontrol_news =
					snd_soc_dapm_alloc_kcontrol(card,
3927 3928 3929
						link_name,
						rtd->dai_link->params,
						rtd->dai_link->num_params,
3930 3931 3932 3933 3934
						w_param_text, &private_value);
		if (!template.kcontrol_news) {
			ret = -ENOMEM;
			goto param_fail;
		}
3935 3936
	} else {
		w_param_text = NULL;
3937
	}
3938
	dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name);
3939

3940
	w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template);
3941
	if (IS_ERR(w))
3942
		goto outfree_kcontrol_news;
3943

3944
	w->priv = rtd;
3945

3946
	return w;
3947 3948 3949

outfree_kcontrol_news:
	devm_kfree(card->dev, (void *)template.kcontrol_news);
3950 3951
	snd_soc_dapm_free_kcontrol(card, &private_value,
				   rtd->dai_link->num_params, w_param_text);
3952
param_fail:
3953
	devm_kfree(card->dev, link_name);
3954
	return ERR_PTR(ret);
3955 3956
}

3957 3958
int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
				 struct snd_soc_dai *dai)
3959
{
3960
	struct snd_soc_dapm_widget template;
3961 3962
	struct snd_soc_dapm_widget *w;

3963 3964 3965 3966 3967 3968
	WARN_ON(dapm->dev != dai->dev);

	memset(&template, 0, sizeof(template));
	template.reg = SND_SOC_NOPM;

	if (dai->driver->playback.stream_name) {
3969
		template.id = snd_soc_dapm_dai_in;
3970 3971 3972
		template.name = dai->driver->playback.stream_name;
		template.sname = dai->driver->playback.stream_name;

3973
		dev_dbg(dai->dev, "ASoC: adding %s widget\n",
3974 3975
			template.name);

3976
		w = snd_soc_dapm_new_control_unlocked(dapm, &template);
3977 3978
		if (IS_ERR(w))
			return PTR_ERR(w);
3979 3980 3981 3982 3983 3984

		w->priv = dai;
		dai->playback_widget = w;
	}

	if (dai->driver->capture.stream_name) {
3985
		template.id = snd_soc_dapm_dai_out;
3986 3987 3988
		template.name = dai->driver->capture.stream_name;
		template.sname = dai->driver->capture.stream_name;

3989
		dev_dbg(dai->dev, "ASoC: adding %s widget\n",
3990 3991
			template.name);

3992
		w = snd_soc_dapm_new_control_unlocked(dapm, &template);
3993 3994
		if (IS_ERR(w))
			return PTR_ERR(w);
3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005

		w->priv = dai;
		dai->capture_widget = w;
	}

	return 0;
}

int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
{
	struct snd_soc_dapm_widget *dai_w, *w;
4006
	struct snd_soc_dapm_widget *src, *sink;
4007 4008 4009 4010
	struct snd_soc_dai *dai;

	/* For each DAI widget... */
	list_for_each_entry(dai_w, &card->widgets, list) {
4011 4012 4013 4014 4015
		switch (dai_w->id) {
		case snd_soc_dapm_dai_in:
		case snd_soc_dapm_dai_out:
			break;
		default:
4016
			continue;
4017
		}
4018

4019 4020 4021 4022 4023 4024 4025
		/* let users know there is no DAI to link */
		if (!dai_w->priv) {
			dev_dbg(card->dev, "dai widget %s has no DAI\n",
				dai_w->name);
			continue;
		}

4026 4027 4028 4029 4030 4031 4032
		dai = dai_w->priv;

		/* ...find all widgets with the same stream and link them */
		list_for_each_entry(w, &card->widgets, list) {
			if (w->dapm != dai_w->dapm)
				continue;

4033 4034 4035
			switch (w->id) {
			case snd_soc_dapm_dai_in:
			case snd_soc_dapm_dai_out:
4036
				continue;
4037 4038 4039
			default:
				break;
			}
4040

4041
			if (!w->sname || !strstr(w->sname, dai_w->sname))
4042 4043
				continue;

4044 4045 4046 4047 4048 4049
			if (dai_w->id == snd_soc_dapm_dai_in) {
				src = dai_w;
				sink = w;
			} else {
				src = w;
				sink = dai_w;
4050
			}
4051 4052
			dev_dbg(dai->dev, "%s -> %s\n", src->name, sink->name);
			snd_soc_dapm_add_path(w->dapm, src, sink, NULL, NULL);
4053 4054 4055
		}
	}

4056 4057
	return 0;
}
4058

4059 4060
static void dapm_connect_dai_link_widgets(struct snd_soc_card *card,
					  struct snd_soc_pcm_runtime *rtd)
4061
{
4062
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
4063
	struct snd_soc_dai *codec_dai;
4064 4065
	struct snd_soc_dapm_widget *playback = NULL, *capture = NULL;
	struct snd_soc_dapm_widget *codec, *playback_cpu, *capture_cpu;
4066 4067
	int i;

4068 4069 4070 4071 4072 4073 4074 4075 4076 4077
	if (rtd->dai_link->params) {
		playback_cpu = cpu_dai->capture_widget;
		capture_cpu = cpu_dai->playback_widget;
	} else {
		playback = cpu_dai->playback_widget;
		capture = cpu_dai->capture_widget;
		playback_cpu = playback;
		capture_cpu = capture;
	}

4078
	for_each_rtd_codec_dai(rtd, i, codec_dai) {
4079 4080

		/* connect BE DAI playback if widgets are valid */
4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092
		codec = codec_dai->playback_widget;

		if (playback_cpu && codec) {
			if (!playback) {
				playback = snd_soc_dapm_new_dai(card, rtd,
								playback_cpu,
								codec);

				snd_soc_dapm_add_path(&card->dapm, playback_cpu,
						      playback, NULL, NULL);
			}

4093
			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
4094 4095
				cpu_dai->component->name, playback_cpu->name,
				codec_dai->component->name, codec->name);
4096

4097 4098
			snd_soc_dapm_add_path(&card->dapm, playback, codec,
					      NULL, NULL);
4099 4100 4101
		}

		/* connect BE DAI capture if widgets are valid */
4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113
		codec = codec_dai->capture_widget;

		if (codec && capture_cpu) {
			if (!capture) {
				capture = snd_soc_dapm_new_dai(card, rtd,
							       codec,
							       capture_cpu);

				snd_soc_dapm_add_path(&card->dapm, capture,
						      capture_cpu, NULL, NULL);
			}

4114
			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
4115 4116
				codec_dai->component->name, codec->name,
				cpu_dai->component->name, capture_cpu->name);
4117

4118 4119
			snd_soc_dapm_add_path(&card->dapm, codec, capture,
					      NULL, NULL);
4120 4121 4122 4123
		}
	}
}

4124
static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
4125
	int event)
4126
{
4127
	struct snd_soc_dapm_widget *w;
4128
	unsigned int ep;
4129

4130 4131 4132 4133
	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
		w = dai->playback_widget;
	else
		w = dai->capture_widget;
4134

4135 4136
	if (w) {
		dapm_mark_dirty(w, "stream event");
4137

4138 4139 4140 4141 4142 4143 4144 4145
		if (w->id == snd_soc_dapm_dai_in) {
			ep = SND_SOC_DAPM_EP_SOURCE;
			dapm_widget_invalidate_input_paths(w);
		} else {
			ep = SND_SOC_DAPM_EP_SINK;
			dapm_widget_invalidate_output_paths(w);
		}

4146 4147
		switch (event) {
		case SND_SOC_DAPM_STREAM_START:
4148
			w->active = 1;
4149
			w->is_ep = ep;
4150 4151
			break;
		case SND_SOC_DAPM_STREAM_STOP:
4152
			w->active = 0;
4153
			w->is_ep = 0;
4154 4155 4156 4157 4158 4159 4160 4161
			break;
		case SND_SOC_DAPM_STREAM_SUSPEND:
		case SND_SOC_DAPM_STREAM_RESUME:
		case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
		case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
			break;
		}
	}
4162
}
4163

4164 4165
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
{
4166
	struct snd_soc_pcm_runtime *rtd;
4167 4168

	/* for each BE DAI link... */
4169
	list_for_each_entry(rtd, &card->rtd_list, list)  {
4170 4171 4172 4173
		/*
		 * dynamic FE links have no fixed DAI mapping.
		 * CODEC<->CODEC links have no direct connection.
		 */
4174
		if (rtd->dai_link->dynamic)
4175 4176 4177 4178 4179 4180
			continue;

		dapm_connect_dai_link_widgets(card, rtd);
	}
}

4181 4182 4183
static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
	int event)
{
4184
	struct snd_soc_dai *codec_dai;
4185 4186
	int i;

4187
	soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event);
4188 4189
	for_each_rtd_codec_dai(rtd, i, codec_dai)
		soc_dapm_dai_stream_event(codec_dai, stream, event);
4190

4191
	dapm_power_widgets(rtd->card, event);
L
Liam Girdwood 已提交
4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204
}

/**
 * snd_soc_dapm_stream_event - send a stream event to the dapm core
 * @rtd: PCM runtime data
 * @stream: stream name
 * @event: stream event
 *
 * Sends a stream event to the dapm core. The core then makes any
 * necessary widget power changes.
 *
 * Returns 0 for success else error.
 */
4205 4206
void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
			      int event)
L
Liam Girdwood 已提交
4207
{
4208
	struct snd_soc_card *card = rtd->card;
L
Liam Girdwood 已提交
4209

4210
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
4211
	soc_dapm_stream_event(rtd, stream, event);
4212
	mutex_unlock(&card->dapm_mutex);
4213 4214
}

4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234
/**
 * snd_soc_dapm_enable_pin_unlocked - enable pin.
 * @dapm: DAPM context
 * @pin: pin name
 *
 * Enables input/output pin and its parents or children widgets iff there is
 * a valid audio route and active audio stream.
 *
 * Requires external locking.
 *
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
				   const char *pin)
{
	return snd_soc_dapm_set_pin(dapm, pin, 1);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked);

4235
/**
4236
 * snd_soc_dapm_enable_pin - enable pin.
L
Liam Girdwood 已提交
4237
 * @dapm: DAPM context
4238
 * @pin: pin name
4239
 *
M
Mark Brown 已提交
4240
 * Enables input/output pin and its parents or children widgets iff there is
4241
 * a valid audio route and active audio stream.
4242
 *
4243 4244
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
4245
 */
L
Liam Girdwood 已提交
4246
int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
4247
{
4248 4249 4250 4251 4252 4253 4254 4255 4256
	int ret;

	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);

	ret = snd_soc_dapm_set_pin(dapm, pin, 1);

	mutex_unlock(&dapm->card->dapm_mutex);

	return ret;
4257 4258
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
4259

4260
/**
4261
 * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
L
Liam Girdwood 已提交
4262
 * @dapm: DAPM context
4263 4264 4265 4266 4267 4268
 * @pin: pin name
 *
 * Enables input/output pin regardless of any other state.  This is
 * intended for use with microphone bias supplies used in microphone
 * jack detection.
 *
4269 4270
 * Requires external locking.
 *
4271 4272 4273
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
4274 4275
int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
					 const char *pin)
4276
{
4277
	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
4278

4279
	if (!w) {
4280
		dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
4281
		return -EINVAL;
4282 4283
	}

4284
	dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin);
4285 4286 4287 4288 4289 4290 4291 4292 4293
	if (!w->connected) {
		/*
		 * w->force does not affect the number of input or output paths,
		 * so we only have to recheck if w->connected is changed
		 */
		dapm_widget_invalidate_input_paths(w);
		dapm_widget_invalidate_output_paths(w);
		w->connected = 1;
	}
4294
	w->force = 1;
4295
	dapm_mark_dirty(w, "force enable");
4296

4297
	return 0;
4298
}
4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked);

/**
 * snd_soc_dapm_force_enable_pin - force a pin to be enabled
 * @dapm: DAPM context
 * @pin: pin name
 *
 * Enables input/output pin regardless of any other state.  This is
 * intended for use with microphone bias supplies used in microphone
 * jack detection.
 *
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
				  const char *pin)
{
	int ret;

	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);

	ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);

	mutex_unlock(&dapm->card->dapm_mutex);

	return ret;
}
4326 4327
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);

4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346
/**
 * snd_soc_dapm_disable_pin_unlocked - disable pin.
 * @dapm: DAPM context
 * @pin: pin name
 *
 * Disables input/output pin and its parents or children widgets.
 *
 * Requires external locking.
 *
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
				    const char *pin)
{
	return snd_soc_dapm_set_pin(dapm, pin, 0);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked);

4347 4348
/**
 * snd_soc_dapm_disable_pin - disable pin.
L
Liam Girdwood 已提交
4349
 * @dapm: DAPM context
4350 4351
 * @pin: pin name
 *
M
Mark Brown 已提交
4352
 * Disables input/output pin and its parents or children widgets.
4353
 *
4354 4355 4356
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
L
Liam Girdwood 已提交
4357 4358
int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
			     const char *pin)
4359
{
4360 4361 4362 4363 4364 4365 4366 4367 4368
	int ret;

	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);

	ret = snd_soc_dapm_set_pin(dapm, pin, 0);

	mutex_unlock(&dapm->card->dapm_mutex);

	return ret;
4369
}
4370
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
4371

4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394
/**
 * snd_soc_dapm_nc_pin_unlocked - permanently disable pin.
 * @dapm: DAPM context
 * @pin: pin name
 *
 * Marks the specified pin as being not connected, disabling it along
 * any parent or child widgets.  At present this is identical to
 * snd_soc_dapm_disable_pin() but in future it will be extended to do
 * additional things such as disabling controls which only affect
 * paths through the pin.
 *
 * Requires external locking.
 *
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
			       const char *pin)
{
	return snd_soc_dapm_set_pin(dapm, pin, 0);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked);

4395 4396
/**
 * snd_soc_dapm_nc_pin - permanently disable pin.
L
Liam Girdwood 已提交
4397
 * @dapm: DAPM context
4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408
 * @pin: pin name
 *
 * Marks the specified pin as being not connected, disabling it along
 * any parent or child widgets.  At present this is identical to
 * snd_soc_dapm_disable_pin() but in future it will be extended to do
 * additional things such as disabling controls which only affect
 * paths through the pin.
 *
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
L
Liam Girdwood 已提交
4409
int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
4410
{
4411 4412 4413 4414 4415 4416 4417 4418 4419
	int ret;

	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);

	ret = snd_soc_dapm_set_pin(dapm, pin, 0);

	mutex_unlock(&dapm->card->dapm_mutex);

	return ret;
4420 4421 4422
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);

4423
/**
4424
 * snd_soc_dapm_get_pin_status - get audio pin status
L
Liam Girdwood 已提交
4425
 * @dapm: DAPM context
4426
 * @pin: audio signal pin endpoint (or start point)
4427
 *
4428
 * Get audio pin status - connected or disconnected.
4429
 *
4430
 * Returns 1 for connected otherwise 0.
4431
 */
L
Liam Girdwood 已提交
4432 4433
int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
				const char *pin)
4434
{
4435
	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
4436

4437 4438
	if (w)
		return w->connected;
4439

4440 4441
	return 0;
}
4442
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
4443

4444 4445
/**
 * snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint
L
Liam Girdwood 已提交
4446
 * @dapm: DAPM context
4447 4448 4449 4450 4451 4452 4453 4454
 * @pin: audio signal pin endpoint (or start point)
 *
 * Mark the given endpoint or pin as ignoring suspend.  When the
 * system is disabled a path between two endpoints flagged as ignoring
 * suspend will not be disabled.  The path must already be enabled via
 * normal means at suspend time, it will not be turned on if it was not
 * already enabled.
 */
L
Liam Girdwood 已提交
4455 4456
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
				const char *pin)
4457
{
4458
	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, false);
4459

4460
	if (!w) {
4461
		dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
4462
		return -EINVAL;
4463 4464
	}

4465 4466 4467
	w->ignore_suspend = 1;

	return 0;
4468 4469 4470
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);

4471 4472
/**
 * snd_soc_dapm_free - free dapm resources
4473
 * @dapm: DAPM context
4474 4475 4476
 *
 * Free all dapm widgets and resources.
 */
L
Liam Girdwood 已提交
4477
void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm)
4478
{
4479
	dapm_debugfs_cleanup(dapm);
L
Liam Girdwood 已提交
4480
	dapm_free_widgets(dapm);
4481
	list_del(&dapm->list);
4482 4483 4484
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_free);

4485
static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm)
M
Mark Brown 已提交
4486
{
4487
	struct snd_soc_card *card = dapm->card;
M
Mark Brown 已提交
4488 4489 4490 4491
	struct snd_soc_dapm_widget *w;
	LIST_HEAD(down_list);
	int powerdown = 0;

4492 4493
	mutex_lock(&card->dapm_mutex);

4494 4495 4496
	list_for_each_entry(w, &dapm->card->widgets, list) {
		if (w->dapm != dapm)
			continue;
M
Mark Brown 已提交
4497
		if (w->power) {
4498
			dapm_seq_insert(w, &down_list, false);
4499
			w->power = 0;
M
Mark Brown 已提交
4500 4501 4502 4503 4504 4505 4506 4507
			powerdown = 1;
		}
	}

	/* If there were no widgets to power down we're already in
	 * standby.
	 */
	if (powerdown) {
4508 4509 4510
		if (dapm->bias_level == SND_SOC_BIAS_ON)
			snd_soc_dapm_set_bias_level(dapm,
						    SND_SOC_BIAS_PREPARE);
4511
		dapm_seq_run(card, &down_list, 0, false);
4512 4513 4514
		if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
			snd_soc_dapm_set_bias_level(dapm,
						    SND_SOC_BIAS_STANDBY);
M
Mark Brown 已提交
4515
	}
4516 4517

	mutex_unlock(&card->dapm_mutex);
4518 4519 4520 4521 4522 4523 4524
}

/*
 * snd_soc_dapm_shutdown - callback for system shutdown
 */
void snd_soc_dapm_shutdown(struct snd_soc_card *card)
{
4525
	struct snd_soc_dapm_context *dapm;
4526

4527
	list_for_each_entry(dapm, &card->dapm_list, list) {
4528 4529 4530 4531 4532 4533
		if (dapm != &card->dapm) {
			soc_dapm_shutdown_dapm(dapm);
			if (dapm->bias_level == SND_SOC_BIAS_STANDBY)
				snd_soc_dapm_set_bias_level(dapm,
							    SND_SOC_BIAS_OFF);
		}
L
Liam Girdwood 已提交
4534
	}
4535 4536 4537 4538 4539

	soc_dapm_shutdown_dapm(&card->dapm);
	if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY)
		snd_soc_dapm_set_bias_level(&card->dapm,
					    SND_SOC_BIAS_OFF);
M
Mark Brown 已提交
4540 4541
}

4542
/* Module information */
4543
MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
4544 4545
MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
MODULE_LICENSE("GPL");