soc-dapm.c 93.8 KB
Newer Older
1 2 3 4
/*
 * soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management
 *
 * Copyright 2005 Wolfson Microelectronics PLC.
5
 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 7 8 9 10 11 12 13 14
 *
 *  This program is free software; you can redistribute  it and/or modify it
 *  under  the terms of  the GNU General  Public License as published by the
 *  Free Software Foundation;  either version 2 of the  License, or (at your
 *  option) any later version.
 *
 *  Features:
 *    o Changes power status of internal codec blocks depending on the
 *      dynamic configuration of codec internal audio paths and active
Mark Brown's avatar
Mark Brown committed
15
 *      DACs/ADCs.
16
 *    o Platform power domain - can support external components i.e. amps and
17
 *      mic/headphone insertion events.
18 19 20
 *    o Automatic Mic Bias support
 *    o Jack insertion power event initiation - e.g. hp insertion will enable
 *      sinks, dacs, etc
21
 *    o Delayed power down of audio subsystem to reduce pops between a quick
22 23 24 25 26 27 28
 *      device reopen.
 *
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
29
#include <linux/async.h>
30 31 32 33 34
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/jiffies.h>
35
#include <linux/debugfs.h>
36
#include <linux/pm_runtime.h>
37
#include <linux/regulator/consumer.h>
38
#include <linux/clk.h>
39
#include <linux/slab.h>
40 41 42
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
43
#include <sound/soc.h>
44 45
#include <sound/initval.h>

Mark Brown's avatar
Mark Brown committed
46 47
#include <trace/events/asoc.h>

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

50 51
/* dapm power sequences - make this per codec in the future */
static int dapm_up_seq[] = {
52 53
	[snd_soc_dapm_pre] = 0,
	[snd_soc_dapm_supply] = 1,
54
	[snd_soc_dapm_regulator_supply] = 1,
55
	[snd_soc_dapm_clock_supply] = 1,
56
	[snd_soc_dapm_micbias] = 2,
57
	[snd_soc_dapm_dai_link] = 2,
58
	[snd_soc_dapm_dai] = 3,
59 60 61 62
	[snd_soc_dapm_aif_in] = 3,
	[snd_soc_dapm_aif_out] = 3,
	[snd_soc_dapm_mic] = 4,
	[snd_soc_dapm_mux] = 5,
63
	[snd_soc_dapm_virt_mux] = 5,
64 65 66 67 68 69
	[snd_soc_dapm_value_mux] = 5,
	[snd_soc_dapm_dac] = 6,
	[snd_soc_dapm_mixer] = 7,
	[snd_soc_dapm_mixer_named_ctl] = 7,
	[snd_soc_dapm_pga] = 8,
	[snd_soc_dapm_adc] = 9,
70
	[snd_soc_dapm_out_drv] = 10,
71 72
	[snd_soc_dapm_hp] = 10,
	[snd_soc_dapm_spk] = 10,
73
	[snd_soc_dapm_line] = 10,
74
	[snd_soc_dapm_post] = 11,
75
};
76

77
static int dapm_down_seq[] = {
78 79 80
	[snd_soc_dapm_pre] = 0,
	[snd_soc_dapm_adc] = 1,
	[snd_soc_dapm_hp] = 2,
81
	[snd_soc_dapm_spk] = 2,
82
	[snd_soc_dapm_line] = 2,
83
	[snd_soc_dapm_out_drv] = 2,
84 85
	[snd_soc_dapm_pga] = 4,
	[snd_soc_dapm_mixer_named_ctl] = 5,
86 87 88 89 90
	[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,
91
	[snd_soc_dapm_virt_mux] = 9,
92
	[snd_soc_dapm_value_mux] = 9,
93 94
	[snd_soc_dapm_aif_in] = 10,
	[snd_soc_dapm_aif_out] = 10,
95
	[snd_soc_dapm_dai] = 10,
96
	[snd_soc_dapm_dai_link] = 11,
97
	[snd_soc_dapm_clock_supply] = 12,
98 99 100
	[snd_soc_dapm_regulator_supply] = 12,
	[snd_soc_dapm_supply] = 12,
	[snd_soc_dapm_post] = 13,
101 102
};

103
static void pop_wait(u32 pop_time)
104 105 106 107 108
{
	if (pop_time)
		schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
}

109
static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
110 111
{
	va_list args;
112
	char *buf;
113

114 115
	if (!pop_time)
		return;
116

117 118 119
	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (buf == NULL)
		return;
120

121 122
	va_start(args, fmt);
	vsnprintf(buf, PAGE_SIZE, fmt, args);
123
	dev_info(dev, "%s", buf);
124
	va_end(args);
125 126

	kfree(buf);
127 128
}

129 130 131 132 133
static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)
{
	return !list_empty(&w->dirty);
}

134
void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
135
{
136 137 138
	if (!dapm_dirty_widget(w)) {
		dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",
			 w->name, reason);
139
		list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);
140
	}
141
}
142
EXPORT_SYMBOL_GPL(dapm_mark_dirty);
143

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm)
{
	struct snd_soc_card *card = dapm->card;
	struct snd_soc_dapm_widget *w;

	mutex_lock(&card->dapm_mutex);

	list_for_each_entry(w, &card->widgets, list) {
		switch (w->id) {
		case snd_soc_dapm_input:
		case snd_soc_dapm_output:
			dapm_mark_dirty(w, "Rechecking inputs and outputs");
			break;
		default:
			break;
		}
	}

	mutex_unlock(&card->dapm_mutex);
}
EXPORT_SYMBOL_GPL(dapm_mark_io_dirty);

166
/* create a new dapm widget */
167
static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
168 169
	const struct snd_soc_dapm_widget *_widget)
{
170
	return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
171 172
}

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
/* get snd_card from DAPM context */
static inline struct snd_card *dapm_get_snd_card(
	struct snd_soc_dapm_context *dapm)
{
	if (dapm->codec)
		return dapm->codec->card->snd_card;
	else if (dapm->platform)
		return dapm->platform->card->snd_card;
	else
		BUG();

	/* unreachable */
	return NULL;
}

/* get soc_card from DAPM context */
static inline struct snd_soc_card *dapm_get_soc_card(
		struct snd_soc_dapm_context *dapm)
{
	if (dapm->codec)
		return dapm->codec->card;
	else if (dapm->platform)
		return dapm->platform->card;
	else
		BUG();

	/* unreachable */
	return NULL;
}

203 204 205 206 207 208 209 210 211 212 213 214 215
static void dapm_reset(struct snd_soc_card *card)
{
	struct snd_soc_dapm_widget *w;

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

	list_for_each_entry(w, &card->widgets, list) {
		w->power_checked = false;
		w->inputs = -1;
		w->outputs = -1;
	}
}

216 217 218 219
static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
{
	if (w->codec)
		return snd_soc_read(w->codec, reg);
220 221 222
	else if (w->platform)
		return snd_soc_platform_read(w->platform, reg);

223
	dev_err(w->dapm->dev, "ASoC: no valid widget read method\n");
224
	return -1;
225 226 227 228 229 230
}

static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
{
	if (w->codec)
		return snd_soc_write(w->codec, reg, val);
231 232 233
	else if (w->platform)
		return snd_soc_platform_write(w->platform, reg, val);

234
	dev_err(w->dapm->dev, "ASoC: no valid widget write method\n");
235
	return -1;
236 237
}

238 239
static inline void soc_widget_lock(struct snd_soc_dapm_widget *w)
{
240
	if (w->codec && !w->codec->using_regmap)
241 242 243 244 245 246 247
		mutex_lock(&w->codec->mutex);
	else if (w->platform)
		mutex_lock(&w->platform->mutex);
}

static inline void soc_widget_unlock(struct snd_soc_dapm_widget *w)
{
248
	if (w->codec && !w->codec->using_regmap)
249 250 251 252 253 254
		mutex_unlock(&w->codec->mutex);
	else if (w->platform)
		mutex_unlock(&w->platform->mutex);
}

static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
255 256
	unsigned short reg, unsigned int mask, unsigned int value)
{
257
	bool change;
258 259 260
	unsigned int old, new;
	int ret;

261 262 263 264 265 266
	if (w->codec && w->codec->using_regmap) {
		ret = regmap_update_bits_check(w->codec->control_data,
					       reg, mask, value, &change);
		if (ret != 0)
			return ret;
	} else {
267
		soc_widget_lock(w);
268
		ret = soc_widget_read(w, reg);
269 270
		if (ret < 0) {
			soc_widget_unlock(w);
271
			return ret;
272
		}
273 274 275 276 277 278

		old = ret;
		new = (old & ~mask) | (value & mask);
		change = old != new;
		if (change) {
			ret = soc_widget_write(w, reg, new);
279 280
			if (ret < 0) {
				soc_widget_unlock(w);
281
				return ret;
282
			}
283
		}
284
		soc_widget_unlock(w);
285 286 287 288 289
	}

	return change;
}

290 291
/**
 * snd_soc_dapm_set_bias_level - set the bias level for the system
292
 * @dapm: DAPM context
293 294 295 296 297 298
 * @level: level to configure
 *
 * Configure the bias (power) levels for the SoC audio device.
 *
 * Returns 0 for success else error.
 */
299
static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
300
				       enum snd_soc_bias_level level)
301
{
302
	struct snd_soc_card *card = dapm->card;
303 304
	int ret = 0;

Mark Brown's avatar
Mark Brown committed
305 306
	trace_snd_soc_bias_level_start(card, level);

307
	if (card && card->set_bias_level)
308
		ret = card->set_bias_level(card, dapm, level);
309 310 311
	if (ret != 0)
		goto out;

312 313 314 315
	if (dapm->codec) {
		if (dapm->codec->driver->set_bias_level)
			ret = dapm->codec->driver->set_bias_level(dapm->codec,
								  level);
316 317
		else
			dapm->bias_level = level;
318
	} else if (!card || dapm != &card->dapm) {
319
		dapm->bias_level = level;
320
	}
321

322 323 324 325
	if (ret != 0)
		goto out;

	if (card && card->set_bias_level_post)
326
		ret = card->set_bias_level_post(card, dapm, level);
327
out:
Mark Brown's avatar
Mark Brown committed
328 329
	trace_snd_soc_bias_level_done(card, level);

330 331 332
	return ret;
}

333 334 335 336 337 338
/* set up initial codec paths */
static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
	struct snd_soc_dapm_path *p, int i)
{
	switch (w->id) {
	case snd_soc_dapm_switch:
339 340
	case snd_soc_dapm_mixer:
	case snd_soc_dapm_mixer_named_ctl: {
341
		int val;
342
		struct soc_mixer_control *mc = (struct soc_mixer_control *)
343
			w->kcontrol_news[i].private_value;
344 345
		unsigned int reg = mc->reg;
		unsigned int shift = mc->shift;
346
		int max = mc->max;
347 348
		unsigned int mask = (1 << fls(max)) - 1;
		unsigned int invert = mc->invert;
349

350
		val = soc_widget_read(w, reg);
351
		val = (val >> shift) & mask;
352 353
		if (invert)
			val = max - val;
354

355
		p->connect = !!val;
356 357 358
	}
	break;
	case snd_soc_dapm_mux: {
359 360
		struct soc_enum *e = (struct soc_enum *)
			w->kcontrol_news[i].private_value;
361
		int val, item;
362

363
		val = soc_widget_read(w, e->reg);
364
		item = (val >> e->shift_l) & e->mask;
365 366

		p->connect = 0;
367
		for (i = 0; i < e->max; i++) {
368 369 370 371 372
			if (!(strcmp(p->name, e->texts[i])) && item == i)
				p->connect = 1;
		}
	}
	break;
373
	case snd_soc_dapm_virt_mux: {
374 375
		struct soc_enum *e = (struct soc_enum *)
			w->kcontrol_news[i].private_value;
376 377 378 379 380 381 382 383 384 385 386 387

		p->connect = 0;
		/* 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.
		 */
		if (!strcmp(p->name, e->texts[0]))
			p->connect = 1;
	}
	break;
388
	case snd_soc_dapm_value_mux: {
389
		struct soc_enum *e = (struct soc_enum *)
390
			w->kcontrol_news[i].private_value;
391 392
		int val, item;

393
		val = soc_widget_read(w, e->reg);
394 395 396 397 398 399 400 401 402 403 404 405 406
		val = (val >> e->shift_l) & e->mask;
		for (item = 0; item < e->max; item++) {
			if (val == e->values[item])
				break;
		}

		p->connect = 0;
		for (i = 0; i < e->max; i++) {
			if (!(strcmp(p->name, e->texts[i])) && item == i)
				p->connect = 1;
		}
	}
	break;
407
	/* does not affect routing - always connected */
408
	case snd_soc_dapm_pga:
409
	case snd_soc_dapm_out_drv:
410 411 412
	case snd_soc_dapm_output:
	case snd_soc_dapm_adc:
	case snd_soc_dapm_input:
413
	case snd_soc_dapm_siggen:
414 415 416
	case snd_soc_dapm_dac:
	case snd_soc_dapm_micbias:
	case snd_soc_dapm_vmid:
417
	case snd_soc_dapm_supply:
418
	case snd_soc_dapm_regulator_supply:
419
	case snd_soc_dapm_clock_supply:
420 421
	case snd_soc_dapm_aif_in:
	case snd_soc_dapm_aif_out:
422
	case snd_soc_dapm_dai:
423 424 425 426
	case snd_soc_dapm_hp:
	case snd_soc_dapm_mic:
	case snd_soc_dapm_spk:
	case snd_soc_dapm_line:
427
	case snd_soc_dapm_dai_link:
428 429 430
		p->connect = 1;
	break;
	/* does affect routing - dynamically connected */
431 432 433 434 435 436 437
	case snd_soc_dapm_pre:
	case snd_soc_dapm_post:
		p->connect = 0;
	break;
	}
}

Mark Brown's avatar
Mark Brown committed
438
/* connect mux widget to its interconnecting audio paths */
439
static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
440 441 442 443 444 445 446
	struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
	struct snd_soc_dapm_path *path, const char *control_name,
	const struct snd_kcontrol_new *kcontrol)
{
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
	int i;

447
	for (i = 0; i < e->max; i++) {
448
		if (!(strcmp(control_name, e->texts[i]))) {
449
			list_add(&path->list, &dapm->card->paths);
450 451 452 453 454 455 456 457 458 459 460
			list_add(&path->list_sink, &dest->sources);
			list_add(&path->list_source, &src->sinks);
			path->name = (char*)e->texts[i];
			dapm_set_path_status(dest, path, 0);
			return 0;
		}
	}

	return -ENODEV;
}

Mark Brown's avatar
Mark Brown committed
461
/* connect mixer widget to its interconnecting audio paths */
462
static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,
463 464 465 466 467 468 469
	struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
	struct snd_soc_dapm_path *path, const char *control_name)
{
	int i;

	/* search for mixer kcontrol */
	for (i = 0; i < dest->num_kcontrols; i++) {
470
		if (!strcmp(control_name, dest->kcontrol_news[i].name)) {
471
			list_add(&path->list, &dapm->card->paths);
472 473
			list_add(&path->list_sink, &dest->sources);
			list_add(&path->list_source, &src->sinks);
474
			path->name = dest->kcontrol_news[i].name;
475 476 477 478 479 480 481
			dapm_set_path_status(dest, path, i);
			return 0;
		}
	}
	return -ENODEV;
}

482
static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
483
	struct snd_soc_dapm_widget *kcontrolw,
484 485 486 487 488 489 490 491 492
	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) {
493 494
		if (w == kcontrolw || w->dapm != kcontrolw->dapm)
			continue;
495 496 497 498 499 500 501 502 503 504 505 506
		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;
}

507 508 509 510 511 512
/*
 * 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
 */
static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
	int kci, struct snd_soc_dapm_path *path)
513
{
514
	struct snd_soc_dapm_context *dapm = w->dapm;
515
	struct snd_card *card = dapm->card->snd_card;
516
	const char *prefix;
517 518 519
	size_t prefix_len;
	int shared;
	struct snd_kcontrol *kcontrol;
520
	struct snd_soc_dapm_widget_list *wlist;
521
	int wlistentries;
522
	size_t wlistsize;
523 524 525 526 527
	bool wname_in_long_name, kcname_in_long_name;
	size_t name_len;
	char *long_name;
	const char *name;
	int ret;
528 529 530 531 532

	if (dapm->codec)
		prefix = dapm->codec->name_prefix;
	else
		prefix = NULL;
533

534 535 536 537 538
	if (prefix)
		prefix_len = strlen(prefix) + 1;
	else
		prefix_len = 0;

539 540
	shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],
					 &kcontrol);
541

542 543 544 545 546 547 548
	if (kcontrol) {
		wlist = kcontrol->private_data;
		wlistentries = wlist->num_widgets + 1;
	} else {
		wlist = NULL;
		wlistentries = 1;
	}
549

550 551 552 553 554 555 556 557 558 559
	wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
			wlistentries * sizeof(struct snd_soc_dapm_widget *);
	wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
	if (wlist == NULL) {
		dev_err(dapm->dev, "ASoC: can't allocate widget list for %s\n",
			w->name);
		return -ENOMEM;
	}
	wlist->num_widgets = wlistentries;
	wlist->widgets[wlistentries - 1] = w;
560

561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
	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:
				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;
			case snd_soc_dapm_mux:
			case snd_soc_dapm_virt_mux:
			case snd_soc_dapm_value_mux:
				wname_in_long_name = true;
				kcname_in_long_name = false;
				break;
			default:
				kfree(wlist);
				return -EINVAL;
585
			}
586 587 588 589 590
		}

		if (wname_in_long_name && kcname_in_long_name) {
			name_len = strlen(w->name) - prefix_len + 1 +
				   strlen(w->kcontrol_news[kci].name) + 1;
591

592 593 594
			long_name = kmalloc(name_len, GFP_KERNEL);
			if (long_name == NULL) {
				kfree(wlist);
595 596
				return -ENOMEM;
			}
597 598 599 600 601 602

			/*
			 * 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.
603
			 */
604 605 606 607 608 609 610 611 612 613 614 615 616
			snprintf(long_name, name_len, "%s %s",
				 w->name + prefix_len,
				 w->kcontrol_news[kci].name);
			long_name[name_len - 1] = '\0';

			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;
		}
617

618 619 620 621 622 623 624 625 626 627 628
		kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name,
					prefix);
		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);
			kfree(wlist);
			kfree(long_name);
			return ret;
		}
629

630 631
		path->long_name = long_name;
	}
632

633 634 635
	kcontrol->private_data = wlist;
	w->kcontrols[kci] = kcontrol;
	path->kcontrol = kcontrol;
636

637 638
	return 0;
}
639

640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
/* 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;

	/* add kcontrol */
	for (i = 0; i < w->num_kcontrols; i++) {
		/* match name */
		list_for_each_entry(path, &w->sources, list_sink) {
			/* mixer/mux paths name must match control name */
			if (path->name != (char *)w->kcontrol_news[i].name)
				continue;

			if (w->kcontrols[i]) {
				path->kcontrol = w->kcontrols[i];
				continue;
657
			}
658 659 660 661

			ret = dapm_create_or_share_mixmux_kcontrol(w, i, path);
			if (ret < 0)
				return ret;
662 663
		}
	}
664 665

	return 0;
666 667 668
}

/* create new dapm mux control */
669
static int dapm_new_mux(struct snd_soc_dapm_widget *w)
670
{
671
	struct snd_soc_dapm_context *dapm = w->dapm;
672
	struct snd_soc_dapm_path *path;
673
	int ret;
674

675 676
	if (w->num_kcontrols != 1) {
		dev_err(dapm->dev,
677
			"ASoC: mux %s has incorrect number of controls\n",
678
			w->name);
679 680 681
		return -EINVAL;
	}

682 683 684 685 686
	path = list_first_entry(&w->sources, struct snd_soc_dapm_path,
				list_sink);
	if (!path) {
		dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name);
		return -EINVAL;
687
	}
688

689 690 691
	ret = dapm_create_or_share_mixmux_kcontrol(w, 0, path);
	if (ret < 0)
		return ret;
692

693
	list_for_each_entry(path, &w->sources, list_sink)
694
		path->kcontrol = w->kcontrols[0];
695

696
	return 0;
697 698 699
}

/* create new dapm volume control */
700
static int dapm_new_pga(struct snd_soc_dapm_widget *w)
701
{
702
	if (w->num_kcontrols)
703
		dev_err(w->dapm->dev,
704
			"ASoC: PGA controls not supported: '%s'\n", w->name);
705

706
	return 0;
707 708 709
}

/* reset 'walked' bit for each dapm path */
710 711
static void dapm_clear_walk_output(struct snd_soc_dapm_context *dapm,
				   struct list_head *sink)
712 713 714
{
	struct snd_soc_dapm_path *p;

715 716 717 718 719 720
	list_for_each_entry(p, sink, list_source) {
		if (p->walked) {
			p->walked = 0;
			dapm_clear_walk_output(dapm, &p->sink->sinks);
		}
	}
721 722
}

723 724
static void dapm_clear_walk_input(struct snd_soc_dapm_context *dapm,
				  struct list_head *source)
725 726 727
{
	struct snd_soc_dapm_path *p;

728 729 730 731 732 733
	list_for_each_entry(p, source, list_sink) {
		if (p->walked) {
			p->walked = 0;
			dapm_clear_walk_input(dapm, &p->source->sources);
		}
	}
734 735
}

736

737 738 739 740 741 742
/* 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)
{
743
	int level = snd_power_get_state(widget->dapm->card->snd_card);
744

745
	switch (level) {
746 747
	case SNDRV_CTL_POWER_D3hot:
	case SNDRV_CTL_POWER_D3cold:
748
		if (widget->ignore_suspend)
749
			dev_dbg(widget->dapm->dev, "ASoC: %s ignoring suspend\n",
750
				widget->name);
751
		return widget->ignore_suspend;
752 753 754 755 756
	default:
		return 1;
	}
}

757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
/* add widget to list if it's not already in the list */
static int dapm_list_add_widget(struct snd_soc_dapm_widget_list **list,
	struct snd_soc_dapm_widget *w)
{
	struct snd_soc_dapm_widget_list *wlist;
	int wlistsize, wlistentries, i;

	if (*list == NULL)
		return -EINVAL;

	wlist = *list;

	/* is this widget already in the list */
	for (i = 0; i < wlist->num_widgets; i++) {
		if (wlist->widgets[i] == w)
			return 0;
	}

	/* allocate some new space */
	wlistentries = wlist->num_widgets + 1;
	wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
			wlistentries * sizeof(struct snd_soc_dapm_widget *);
	*list = krealloc(wlist, wlistsize, GFP_KERNEL);
	if (*list == NULL) {
781
		dev_err(w->dapm->dev, "ASoC: can't allocate widget list for %s\n",
782 783 784 785 786 787
			w->name);
		return -ENOMEM;
	}
	wlist = *list;

	/* insert the widget */
788
	dev_dbg(w->dapm->dev, "ASoC: added %s in widget list pos %d\n",
789 790 791 792 793 794 795
			w->name, wlist->num_widgets);

	wlist->widgets[wlist->num_widgets] = w;
	wlist->num_widgets++;
	return 1;
}

796 797 798 799
/*
 * Recursively check for a completed path to an active or physically connected
 * output widget. Returns number of complete paths.
 */
800 801
static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
	struct snd_soc_dapm_widget_list **list)
802 803 804 805
{
	struct snd_soc_dapm_path *path;
	int con = 0;

806 807 808
	if (widget->outputs >= 0)
		return widget->outputs;

809 810
	DAPM_UPDATE_STAT(widget, path_checks);

811 812 813
	switch (widget->id) {
	case snd_soc_dapm_supply:
	case snd_soc_dapm_regulator_supply:
814
	case snd_soc_dapm_clock_supply:
815
		return 0;
816 817 818
	default:
		break;
	}
819

820 821 822
	switch (widget->id) {
	case snd_soc_dapm_adc:
	case snd_soc_dapm_aif_out:
823
	case snd_soc_dapm_dai:
824 825 826 827
		if (widget->active) {
			widget->outputs = snd_soc_dapm_suspend_check(widget);
			return widget->outputs;
		}
828 829 830
	default:
		break;
	}
831 832 833

	if (widget->connected) {
		/* connected pin ? */
834 835 836 837
		if (widget->id == snd_soc_dapm_output && !widget->ext) {
			widget->outputs = snd_soc_dapm_suspend_check(widget);
			return widget->outputs;
		}
838 839

		/* connected jack or spk ? */
840 841 842 843 844 845 846
		if (widget->id == snd_soc_dapm_hp ||
		    widget->id == snd_soc_dapm_spk ||
		    (widget->id == snd_soc_dapm_line &&
		     !list_empty(&widget->sources))) {
			widget->outputs = snd_soc_dapm_suspend_check(widget);
			return widget->outputs;
		}
847 848 849
	}

	list_for_each_entry(path, &widget->sinks, list_source) {
850 851
		DAPM_UPDATE_STAT(widget, neighbour_checks);

852 853 854
		if (path->weak)
			continue;

Mark Brown's avatar
Mark Brown committed
855 856 857
		if (path->walking)
			return 1;

858 859 860
		if (path->walked)
			continue;

861 862
		trace_snd_soc_dapm_output_path(widget, path);

863 864
		if (path->sink && path->connect) {
			path->walked = 1;
Mark Brown's avatar
Mark Brown committed
865
			path->walking = 1;
866 867 868 869 870 871

			/* do we need to add this widget to the list ? */
			if (list) {
				int err;
				err = dapm_list_add_widget(list, path->sink);
				if (err < 0) {
872 873
					dev_err(widget->dapm->dev,
						"ASoC: could not add widget %s\n",
874
						widget->name);
Mark Brown's avatar
Mark Brown committed
875
					path->walking = 0;
876 877 878 879 880
					return con;
				}
			}

			con += is_connected_output_ep(path->sink, list);
Mark Brown's avatar
Mark Brown committed
881 882

			path->walking = 0;
883 884 885
		}
	}

886 887
	widget->outputs = con;

888 889 890 891 892 893 894
	return con;
}

/*
 * Recursively check for a completed path to an active or physically connected
 * input widget. Returns number of complete paths.
 */
895 896
static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
	struct snd_soc_dapm_widget_list **list)
897 898 899 900
{
	struct snd_soc_dapm_path *path;
	int con = 0;

901 902 903
	if (widget->inputs >= 0)
		return widget->inputs;

904 905
	DAPM_UPDATE_STAT(widget, path_checks);

906 907 908
	switch (widget->id) {
	case snd_soc_dapm_supply:
	case snd_soc_dapm_regulator_supply:
909
	case snd_soc_dapm_clock_supply:
910
		return 0;
911 912 913
	default:
		break;
	}
914

915
	/* active stream ? */
916 917 918
	switch (widget->id) {
	case snd_soc_dapm_dac:
	case snd_soc_dapm_aif_in:
919
	case snd_soc_dapm_dai:
920 921 922 923
		if (widget->active) {
			widget->inputs = snd_soc_dapm_suspend_check(widget);
			return widget->inputs;
		}
924 925 926
	default:
		break;
	}
927 928 929

	if (widget->connected) {
		/* connected pin ? */
930 931 932 933
		if (widget->id == snd_soc_dapm_input && !widget->ext) {
			widget->inputs = snd_soc_dapm_suspend_check(widget);
			return widget->inputs;
		}
934 935

		/* connected VMID/Bias for lower pops */
936 937 938 939
		if (widget->id == snd_soc_dapm_vmid) {
			widget->inputs = snd_soc_dapm_suspend_check(widget);
			return widget->inputs;
		}
940 941

		/* connected jack ? */
942
		if (widget->id == snd_soc_dapm_mic ||
943 944 945 946 947 948
		    (widget->id == snd_soc_dapm_line &&
		     !list_empty(&widget->sinks))) {
			widget->inputs = snd_soc_dapm_suspend_check(widget);
			return widget->inputs;
		}

949 950 951 952 953
		/* signal generator */
		if (widget->id == snd_soc_dapm_siggen) {
			widget->inputs = snd_soc_dapm_suspend_check(widget);
			return widget->inputs;
		}
954 955 956
	}

	list_for_each_entry(path, &widget->sources, list_sink) {
957 958
		DAPM_UPDATE_STAT(widget, neighbour_checks);

959 960 961
		if (path->weak)
			continue;

Mark Brown's avatar
Mark Brown committed
962 963 964
		if (path->walking)
			return 1;

965 966 967
		if (path->walked)
			continue;

968 969
		trace_snd_soc_dapm_input_path(widget, path);

970 971
		if (path->source && path->connect) {
			path->walked = 1;
Mark Brown's avatar
Mark Brown committed
972
			path->walking = 1;
973 974 975 976

			/* do we need to add this widget to the list ? */
			if (list) {
				int err;
977
				err = dapm_list_add_widget(list, path->source);
978
				if (err < 0) {
979 980
					dev_err(widget->dapm->dev,
						"ASoC: could not add widget %s\n",
981
						widget->name);
Mark Brown's avatar
Mark Brown committed
982
					path->walking = 0;
983 984 985 986 987
					return con;
				}
			}

			con += is_connected_input_ep(path->source, list);
Mark Brown's avatar
Mark Brown committed
988 989

			path->walking = 0;
990 991 992
		}
	}

993 994
	widget->inputs = con;

995 996 997
	return con;
}

998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
/**
 * 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.
 *
 * Queries DAPM graph as to whether an valid audio stream path exists for
 * the initial stream specified by name. This takes into account
 * current mixer and mux kcontrol settings. Creates list of valid widgets.
 *
 * Returns the number of valid paths or negative error.
 */
int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
	struct snd_soc_dapm_widget_list **list)
{
	struct snd_soc_card *card = dai->card;
	int paths;

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

1019
	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1020
		paths = is_connected_output_ep(dai->playback_widget, list);
1021 1022 1023
		dapm_clear_walk_output(&card->dapm,
				       &dai->playback_widget->sinks);
	} else {
1024
		paths = is_connected_input_ep(dai->capture_widget, list);
1025 1026 1027
		dapm_clear_walk_input(&card->dapm,
				      &dai->capture_widget->sources);
	}
1028 1029 1030 1031 1032 1033 1034

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

	return paths;
}

1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
/*
 * Handler for generic register modifier widget.
 */
int dapm_reg_event(struct snd_soc_dapm_widget *w,
		   struct snd_kcontrol *kcontrol, int event)
{
	unsigned int val;

	if (SND_SOC_DAPM_EVENT_ON(event))
		val = w->on_val;
	else
		val = w->off_val;

1048
	soc_widget_update_bits_locked(w, -(w->reg + 1),
1049 1050 1051 1052
			    w->mask << w->shift, val << w->shift);

	return 0;
}