soc-dapm.c 97.5 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
M
Mark Brown 已提交
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>
L
Liam Girdwood 已提交
43
#include <sound/soc.h>
44 45
#include <sound/initval.h>

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

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

50 51 52 53 54 55 56 57 58
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));
static struct snd_soc_dapm_widget *
snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
			 const struct snd_soc_dapm_widget *widget);

59 60
/* dapm power sequences - make this per codec in the future */
static int dapm_up_seq[] = {
61
	[snd_soc_dapm_pre] = 0,
62
	[snd_soc_dapm_regulator_supply] = 1,
63
	[snd_soc_dapm_clock_supply] = 1,
64 65
	[snd_soc_dapm_supply] = 2,
	[snd_soc_dapm_micbias] = 3,
66
	[snd_soc_dapm_dai_link] = 2,
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
	[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,
	[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,
85
};
86

87
static int dapm_down_seq[] = {
88
	[snd_soc_dapm_pre] = 0,
89 90 91 92 93 94
	[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,
95
	[snd_soc_dapm_pga] = 4,
96
	[snd_soc_dapm_switch] = 5,
97
	[snd_soc_dapm_mixer_named_ctl] = 5,
98 99 100 101 102
	[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,
103 104
	[snd_soc_dapm_aif_in] = 10,
	[snd_soc_dapm_aif_out] = 10,
105 106
	[snd_soc_dapm_dai_in] = 10,
	[snd_soc_dapm_dai_out] = 10,
107 108
	[snd_soc_dapm_dai_link] = 11,
	[snd_soc_dapm_supply] = 12,
109 110 111
	[snd_soc_dapm_clock_supply] = 13,
	[snd_soc_dapm_regulator_supply] = 13,
	[snd_soc_dapm_post] = 14,
112 113
};

114
static void pop_wait(u32 pop_time)
115 116 117 118 119
{
	if (pop_time)
		schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
}

120
static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
121 122
{
	va_list args;
123
	char *buf;
124

125 126
	if (!pop_time)
		return;
127

128 129 130
	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (buf == NULL)
		return;
131

132 133
	va_start(args, fmt);
	vsnprintf(buf, PAGE_SIZE, fmt, args);
134
	dev_info(dev, "%s", buf);
135
	va_end(args);
136 137

	kfree(buf);
138 139
}

140 141 142 143 144
static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)
{
	return !list_empty(&w->dirty);
}

145
void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
146
{
147 148 149
	if (!dapm_dirty_widget(w)) {
		dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",
			 w->name, reason);
150
		list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);
151
	}
152
}
153
EXPORT_SYMBOL_GPL(dapm_mark_dirty);
154

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
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);

177
/* create a new dapm widget */
178
static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
179 180
	const struct snd_soc_dapm_widget *_widget)
{
181
	return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
182 183
}

184
struct dapm_kcontrol_data {
185
	unsigned int value;
186
	struct snd_soc_dapm_widget *widget;
187
	struct list_head paths;
188
	struct snd_soc_dapm_widget_list *wlist;
189 190 191 192 193 194
};

static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
	struct snd_kcontrol *kcontrol)
{
	struct dapm_kcontrol_data *data;
195
	struct soc_mixer_control *mc;
196

197
	data = kzalloc(sizeof(*data), GFP_KERNEL);
198 199 200 201 202 203 204
	if (!data) {
		dev_err(widget->dapm->dev,
				"ASoC: can't allocate kcontrol data for %s\n",
				widget->name);
		return -ENOMEM;
	}

205
	INIT_LIST_HEAD(&data->paths);
206

207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
	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;

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

			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;
			template.name = kcontrol->id.name;

228 229
			data->value = template.on_val;

230 231 232 233 234 235 236 237 238 239 240 241
			data->widget = snd_soc_dapm_new_control(widget->dapm,
				&template);
			if (!data->widget) {
				kfree(data);
				return -ENOMEM;
			}
		}
		break;
	default:
		break;
	}

242 243 244 245 246 247 248 249
	kcontrol->private_data = data;

	return 0;
}

static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);
250
	kfree(data->widget);
251
	kfree(data->wlist);
252 253 254 255 256 257 258 259
	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);

260
	return data->wlist;
261 262 263 264 265 266
}

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);
267 268
	struct snd_soc_dapm_widget_list *new_wlist;
	unsigned int n;
269

270 271 272 273 274 275 276 277
	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)
278 279
		return -ENOMEM;

280 281
	new_wlist->widgets[n - 1] = widget;
	new_wlist->num_widgets = n;
282

283
	data->wlist = new_wlist;
284 285 286 287

	return 0;
}

288 289 290 291 292 293
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);
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308

	if (data->widget) {
		snd_soc_dapm_add_path(data->widget->dapm, data->widget,
		    path->source, NULL, NULL);
	}
}

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;
309 310 311 312 313 314 315 316 317 318 319 320 321 322
}

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)

323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
static unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);

	return data->value;
}

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;

338 339 340
	if (data->widget)
		data->widget->on_val = value;

341 342 343 344 345
	data->value = value;

	return true;
}

346 347 348 349 350 351
/**
 * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
 * @kcontrol: The kcontrol
 */
struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol)
{
352
	return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec;
353 354 355
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec);

356 357 358 359 360 361 362
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) {
363
		w->new_power = w->power;
364 365 366 367 368 369
		w->power_checked = false;
		w->inputs = -1;
		w->outputs = -1;
	}
}

370 371
static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg,
	unsigned int *value)
372
{
373 374 375 376 377 378 379
	if (w->codec) {
		*value = snd_soc_read(w->codec, reg);
		return 0;
	} else if (w->platform) {
		*value = snd_soc_platform_read(w->platform, reg);
		return 0;
	}
380

381
	dev_err(w->dapm->dev, "ASoC: no valid widget read method\n");
382
	return -1;
383 384
}

385 386
static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg,
	unsigned int val)
387 388 389
{
	if (w->codec)
		return snd_soc_write(w->codec, reg, val);
390 391 392
	else if (w->platform)
		return snd_soc_platform_write(w->platform, reg, val);

393
	dev_err(w->dapm->dev, "ASoC: no valid widget write method\n");
394
	return -1;
395 396
}

397 398
static inline void soc_widget_lock(struct snd_soc_dapm_widget *w)
{
399
	if (w->codec && !w->codec->using_regmap)
400 401 402 403 404 405 406
		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)
{
407
	if (w->codec && !w->codec->using_regmap)
408 409 410 411 412
		mutex_unlock(&w->codec->mutex);
	else if (w->platform)
		mutex_unlock(&w->platform->mutex);
}

413 414 415 416 417 418
static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
{
	if (dapm->codec && dapm->codec->using_regmap)
		regmap_async_complete(dapm->codec->control_data);
}

419
static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
420 421
	unsigned short reg, unsigned int mask, unsigned int value)
{
422
	bool change;
423 424 425
	unsigned int old, new;
	int ret;

426
	if (w->codec && w->codec->using_regmap) {
427 428 429
		ret = regmap_update_bits_check_async(w->codec->control_data,
						     reg, mask, value,
						     &change);
430 431 432
		if (ret != 0)
			return ret;
	} else {
433
		soc_widget_lock(w);
434
		ret = soc_widget_read(w, reg, &old);
435 436
		if (ret < 0) {
			soc_widget_unlock(w);
437
			return ret;
438
		}
439 440 441 442 443

		new = (old & ~mask) | (value & mask);
		change = old != new;
		if (change) {
			ret = soc_widget_write(w, reg, new);
444 445
			if (ret < 0) {
				soc_widget_unlock(w);
446
				return ret;
447
			}
448
		}
449
		soc_widget_unlock(w);
450 451 452 453 454
	}

	return change;
}

455 456
/**
 * snd_soc_dapm_set_bias_level - set the bias level for the system
457
 * @dapm: DAPM context
458 459 460 461 462 463
 * @level: level to configure
 *
 * Configure the bias (power) levels for the SoC audio device.
 *
 * Returns 0 for success else error.
 */
464
static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
L
Liam Girdwood 已提交
465
				       enum snd_soc_bias_level level)
466
{
467
	struct snd_soc_card *card = dapm->card;
468 469
	int ret = 0;

M
Mark Brown 已提交
470 471
	trace_snd_soc_bias_level_start(card, level);

472
	if (card && card->set_bias_level)
473
		ret = card->set_bias_level(card, dapm, level);
474 475 476
	if (ret != 0)
		goto out;

477 478 479 480
	if (dapm->codec) {
		if (dapm->codec->driver->set_bias_level)
			ret = dapm->codec->driver->set_bias_level(dapm->codec,
								  level);
481 482
		else
			dapm->bias_level = level;
483
	} else if (!card || dapm != &card->dapm) {
484
		dapm->bias_level = level;
485
	}
486

487 488 489 490
	if (ret != 0)
		goto out;

	if (card && card->set_bias_level_post)
491
		ret = card->set_bias_level_post(card, dapm, level);
492
out:
M
Mark Brown 已提交
493 494
	trace_snd_soc_bias_level_done(card, level);

495 496 497
	return ret;
}

498 499 500 501 502 503
/* 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:
504 505
	case snd_soc_dapm_mixer:
	case snd_soc_dapm_mixer_named_ctl: {
506
		unsigned int val;
507
		struct soc_mixer_control *mc = (struct soc_mixer_control *)
508
			w->kcontrol_news[i].private_value;
509
		int reg = mc->reg;
510
		unsigned int shift = mc->shift;
511
		int max = mc->max;
512 513
		unsigned int mask = (1 << fls(max)) - 1;
		unsigned int invert = mc->invert;
514

515
		if (reg != SND_SOC_NOPM) {
516
			soc_widget_read(w, reg, &val);
517 518 519 520 521 522 523
			val = (val >> shift) & mask;
			if (invert)
				val = max - val;
			p->connect = !!val;
		} else {
			p->connect = 0;
		}
524 525 526 527

	}
	break;
	case snd_soc_dapm_mux: {
528 529
		struct soc_enum *e = (struct soc_enum *)
			w->kcontrol_news[i].private_value;
530
		unsigned int val, item;
531

532 533 534 535 536 537 538 539 540 541 542 543 544
		if (e->reg != SND_SOC_NOPM) {
			soc_widget_read(w, e->reg, &val);
			val = (val >> e->shift_l) & e->mask;
			item = snd_soc_enum_val_to_item(e, val);
		} else {
			/* 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.
			 */
			item = 0;
		}
545

546
		if (item < e->items && !strcmp(p->name, e->texts[item]))
547 548 549
			p->connect = 1;
		else
			p->connect = 0;
550 551
	}
	break;
552
	/* does not affect routing - always connected */
553
	case snd_soc_dapm_pga:
554
	case snd_soc_dapm_out_drv:
555 556 557
	case snd_soc_dapm_output:
	case snd_soc_dapm_adc:
	case snd_soc_dapm_input:
558
	case snd_soc_dapm_siggen:
559 560 561
	case snd_soc_dapm_dac:
	case snd_soc_dapm_micbias:
	case snd_soc_dapm_vmid:
562
	case snd_soc_dapm_supply:
563
	case snd_soc_dapm_regulator_supply:
564
	case snd_soc_dapm_clock_supply:
565 566
	case snd_soc_dapm_aif_in:
	case snd_soc_dapm_aif_out:
567 568
	case snd_soc_dapm_dai_in:
	case snd_soc_dapm_dai_out:
569 570 571 572
	case snd_soc_dapm_hp:
	case snd_soc_dapm_mic:
	case snd_soc_dapm_spk:
	case snd_soc_dapm_line:
573
	case snd_soc_dapm_dai_link:
574
	case snd_soc_dapm_kcontrol:
575 576 577
		p->connect = 1;
	break;
	/* does affect routing - dynamically connected */
578 579 580 581 582 583 584
	case snd_soc_dapm_pre:
	case snd_soc_dapm_post:
		p->connect = 0;
	break;
	}
}

M
Mark Brown 已提交
585
/* connect mux widget to its interconnecting audio paths */
L
Liam Girdwood 已提交
586
static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
587 588 589 590 591 592 593
	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;

594
	for (i = 0; i < e->items; i++) {
595
		if (!(strcmp(control_name, e->texts[i]))) {
596
			list_add(&path->list, &dapm->card->paths);
597 598 599 600 601 602 603 604 605 606 607
			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;
}

M
Mark Brown 已提交
608
/* connect mixer widget to its interconnecting audio paths */
L
Liam Girdwood 已提交
609
static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,
610 611 612 613 614 615 616
	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++) {
617
		if (!strcmp(control_name, dest->kcontrol_news[i].name)) {
618
			list_add(&path->list, &dapm->card->paths);
619 620
			list_add(&path->list_sink, &dest->sources);
			list_add(&path->list_source, &src->sinks);
621
			path->name = dest->kcontrol_news[i].name;
622 623 624 625 626 627 628
			dapm_set_path_status(dest, path, i);
			return 0;
		}
	}
	return -ENODEV;
}

629
static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
630
	struct snd_soc_dapm_widget *kcontrolw,
631 632 633 634 635 636 637 638 639
	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) {
640 641
		if (w == kcontrolw || w->dapm != kcontrolw->dapm)
			continue;
642 643 644 645 646 647 648 649 650 651 652 653
		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;
}

654 655 656 657 658
/*
 * 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,
659
	int kci)
660
{
661
	struct snd_soc_dapm_context *dapm = w->dapm;
662
	struct snd_card *card = dapm->card->snd_card;
663
	const char *prefix;
664 665 666 667 668 669 670
	size_t prefix_len;
	int shared;
	struct snd_kcontrol *kcontrol;
	bool wname_in_long_name, kcname_in_long_name;
	char *long_name;
	const char *name;
	int ret;
671 672 673 674 675

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

677 678 679 680 681
	if (prefix)
		prefix_len = strlen(prefix) + 1;
	else
		prefix_len = 0;

682 683
	shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],
					 &kcontrol);
684

685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
	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:
				wname_in_long_name = true;
				kcname_in_long_name = false;
				break;
			default:
				return -EINVAL;
706
			}
707 708 709 710 711 712 713 714
		}

		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.
715
			 */
716
			long_name = kasprintf(GFP_KERNEL, "%s %s",
717 718
				 w->name + prefix_len,
				 w->kcontrol_news[kci].name);
719
			if (long_name == NULL)
720
				return -ENOMEM;
721 722 723 724 725 726 727 728 729

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

731
		kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name,
732
					prefix);
733
		kfree(long_name);
734 735 736
		if (!kcontrol)
			return -ENOMEM;
		kcontrol->private_free = dapm_kcontrol_free;
737 738 739 740 741 742 743

		ret = dapm_kcontrol_data_alloc(w, kcontrol);
		if (ret) {
			snd_ctl_free_one(kcontrol);
			return ret;
		}

744 745 746 747 748 749 750 751
		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);
			return ret;
		}
	}
752

753 754 755 756
	ret = dapm_kcontrol_add_widget(kcontrol, w);
	if (ret)
		return ret;

757
	w->kcontrols[kci] = kcontrol;
758

759 760
	return 0;
}
761

762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
/* 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]) {
777
				dapm_kcontrol_add_path(w->kcontrols[i], path);
778
				continue;
779
			}
780

781
			ret = dapm_create_or_share_mixmux_kcontrol(w, i);
782 783
			if (ret < 0)
				return ret;
784 785

			dapm_kcontrol_add_path(w->kcontrols[i], path);
786 787
		}
	}
788 789

	return 0;
790 791 792
}

/* create new dapm mux control */
793
static int dapm_new_mux(struct snd_soc_dapm_widget *w)
794
{
795
	struct snd_soc_dapm_context *dapm = w->dapm;
796
	struct snd_soc_dapm_path *path;
797
	int ret;
798

799 800
	if (w->num_kcontrols != 1) {
		dev_err(dapm->dev,
801
			"ASoC: mux %s has incorrect number of controls\n",
802
			w->name);
803 804 805
		return -EINVAL;
	}

806
	if (list_empty(&w->sources)) {
807 808
		dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name);
		return -EINVAL;
809
	}
L
Liam Girdwood 已提交
810

811
	ret = dapm_create_or_share_mixmux_kcontrol(w, 0);
812 813
	if (ret < 0)
		return ret;
814

815
	list_for_each_entry(path, &w->sources, list_sink)
816
		dapm_kcontrol_add_path(w->kcontrols[0], path);
817

818
	return 0;
819 820 821
}

/* create new dapm volume control */
822
static int dapm_new_pga(struct snd_soc_dapm_widget *w)
823
{
824
	if (w->num_kcontrols)
825
		dev_err(w->dapm->dev,
826
			"ASoC: PGA controls not supported: '%s'\n", w->name);
827

828
	return 0;
829 830 831
}

/* reset 'walked' bit for each dapm path */
832 833
static void dapm_clear_walk_output(struct snd_soc_dapm_context *dapm,
				   struct list_head *sink)
834 835 836
{
	struct snd_soc_dapm_path *p;

837 838 839 840 841 842
	list_for_each_entry(p, sink, list_source) {
		if (p->walked) {
			p->walked = 0;
			dapm_clear_walk_output(dapm, &p->sink->sinks);
		}
	}
843 844
}

845 846
static void dapm_clear_walk_input(struct snd_soc_dapm_context *dapm,
				  struct list_head *source)
847 848 849
{
	struct snd_soc_dapm_path *p;

850 851 852 853 854 855
	list_for_each_entry(p, source, list_sink) {
		if (p->walked) {
			p->walked = 0;
			dapm_clear_walk_input(dapm, &p->source->sources);
		}
	}
856 857
}

858

859 860 861 862 863 864
/* 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)
{
865
	int level = snd_power_get_state(widget->dapm->card->snd_card);
866

867
	switch (level) {
868 869
	case SNDRV_CTL_POWER_D3hot:
	case SNDRV_CTL_POWER_D3cold:
870
		if (widget->ignore_suspend)
871
			dev_dbg(widget->dapm->dev, "ASoC: %s ignoring suspend\n",
872
				widget->name);
873
		return widget->ignore_suspend;
874 875 876 877 878
	default:
		return 1;
	}
}

879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902
/* 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) {
903
		dev_err(w->dapm->dev, "ASoC: can't allocate widget list for %s\n",
904 905 906 907 908 909
			w->name);
		return -ENOMEM;
	}
	wlist = *list;

	/* insert the widget */
910
	dev_dbg(w->dapm->dev, "ASoC: added %s in widget list pos %d\n",
911 912 913 914 915 916 917
			w->name, wlist->num_widgets);

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

918 919 920 921
/*
 * Recursively check for a completed path to an active or physically connected
 * output widget. Returns number of complete paths.
 */
922 923
static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
	struct snd_soc_dapm_widget_list **list)
924 925 926 927
{
	struct snd_soc_dapm_path *path;
	int con = 0;

928 929 930
	if (widget->outputs >= 0)
		return widget->outputs;

931 932
	DAPM_UPDATE_STAT(widget, path_checks);

933 934 935
	switch (widget->id) {
	case snd_soc_dapm_supply:
	case snd_soc_dapm_regulator_supply:
936
	case snd_soc_dapm_clock_supply:
937
	case snd_soc_dapm_kcontrol:
938
		return 0;
939 940 941
	default:
		break;
	}
942

943 944 945
	switch (widget->id) {
	case snd_soc_dapm_adc:
	case snd_soc_dapm_aif_out:
946
	case snd_soc_dapm_dai_out:
947 948 949 950
		if (widget->active) {
			widget->outputs = snd_soc_dapm_suspend_check(widget);
			return widget->outputs;
		}
951 952 953
	default:
		break;
	}
954 955 956

	if (widget->connected) {
		/* connected pin ? */
957 958 959 960
		if (widget->id == snd_soc_dapm_output && !widget->ext) {
			widget->outputs = snd_soc_dapm_suspend_check(widget);
			return widget->outputs;
		}
961 962

		/* connected jack or spk ? */
963 964 965 966 967 968 969
		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;
		}
970 971 972
	}

	list_for_each_entry(path, &widget->sinks, list_source) {
973 974
		DAPM_UPDATE_STAT(widget, neighbour_checks);

975 976 977
		if (path->weak)
			continue;

M
Mark Brown 已提交
978 979 980
		if (path->walking)
			return 1;

981 982 983
		if (path->walked)
			continue;

984 985
		trace_snd_soc_dapm_output_path(widget, path);

986 987
		if (path->sink && path->connect) {
			path->walked = 1;
M
Mark Brown 已提交
988
			path->walking = 1;
989 990 991 992 993 994

			/* 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) {
995 996
					dev_err(widget->dapm->dev,
						"ASoC: could not add widget %s\n",
997
						widget->name);
M
Mark Brown 已提交
998
					path->walking = 0;
999 1000 1001 1002 1003
					return con;
				}
			}

			con += is_connected_output_ep(path->sink, list);
M
Mark Brown 已提交
1004 1005

			path->walking = 0;
1006 1007 1008
		}
	}

1009 1010
	widget->outputs = con;

1011 1012 1013 1014 1015 1016 1017
	return con;
}

/*
 * Recursively check for a completed path to an active or physically connected
 * input widget. Returns number of complete paths.
 */
1018 1019
static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
	struct snd_soc_dapm_widget_list **list)
1020 1021 1022 1023
{
	struct snd_soc_dapm_path *path;
	int con = 0;

1024 1025 1026
	if (widget->inputs >= 0)
		return widget->inputs;

1027 1028
	DAPM_UPDATE_STAT(widget, path_checks);

1029 1030 1031
	switch (widget->id) {
	case snd_soc_dapm_supply:
	case snd_soc_dapm_regulator_supply:
1032
	case snd_soc_dapm_clock_supply:
1033
	case snd_soc_dapm_kcontrol:
1034
		return 0;
1035 1036 1037
	default:
		break;
	}
1038

1039
	/* active stream ? */
1040 1041 1042
	switch (widget->id) {
	case snd_soc_dapm_dac:
	case snd_soc_dapm_aif_in:
1043
	case snd_soc_dapm_dai_in:
1044 1045 1046 1047
		if (widget->active) {
			widget->inputs = snd_soc_dapm_suspend_check(widget);
			return widget->inputs;
		}
1048 1049 1050
	default:
		break;
	}
1051 1052 1053

	if (widget->connected) {
		/* connected pin ? */
1054 1055 1056 1057
		if (widget->id == snd_soc_dapm_input && !widget->ext) {
			widget->inputs = snd_soc_dapm_suspend_check(widget);
			return widget->inputs;
		}
1058 1059

		/* connected VMID/Bias for lower pops */
1060 1061 1062 1063
		if (widget->id == snd_soc_dapm_vmid) {
			widget->inputs = snd_soc_dapm_suspend_check(widget);
			return widget->inputs;
		}
1064 1065

		/* connected jack ? */
1066
		if (widget->id == snd_soc_dapm_mic ||
1067 1068 1069 1070 1071 1072
		    (widget->id == snd_soc_dapm_line &&
		     !list_empty(&widget->sinks))) {
			widget->inputs = snd_soc_dapm_suspend_check(widget);
			return widget->inputs;
		}

1073 1074 1075 1076 1077
		/* signal generator */
		if (widget->id == snd_soc_dapm_siggen) {
			widget->inputs = snd_soc_dapm_suspend_check(widget);
			return widget->inputs;
		}
1078 1079 1080
	}

	list_for_each_entry(path, &widget->sources, list_sink) {
1081 1082
		DAPM_UPDATE_STAT(widget, neighbour_checks);

1083 1084 1085
		if (path->weak)
			continue;

M
Mark Brown 已提交
1086 1087 1088
		if (path->walking)
			return 1;

1089 1090 1091
		if (path->walked)
			continue;

1092 1093
		trace_snd_soc_dapm_input_path(widget, path);

1094 1095
		if (path->source && path->connect) {
			path->walked = 1;
M
Mark Brown 已提交
1096
			path->walking = 1;
1097 1098 1099 1100

			/* do we need to add this widget to the list ? */
			if (list) {
				int err;
1101
				err = dapm_list_add_widget(list, path->source);
1102
				if (err < 0) {
1103 1104
					dev_err(widget->dapm->dev,
						"ASoC: could not add widget %s\n",
1105
						widget->name);
M
Mark Brown 已提交
1106
					path->walking = 0;
1107 1108 1109 1110 1111
					return con;
				}
			}

			con += is_connected_input_ep(path->source, list);
M
Mark Brown 已提交
1112 1113

			path->walking = 0;
1114 1115 1116
		}
	}

1117 1118
	widget->inputs = con;

1119 1120 1121
	return con;
}

1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
/**
 * 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);

1143
	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1144
		paths = is_connected_output_ep(dai->playback_widget, list);
1145 1146 1147
		dapm_clear_walk_output(&card->dapm,
				       &dai->playback_widget->sinks);
	} else {
1148
		paths = is_connected_input_ep(dai->capture_widget, list);
1149 1150 1151
		dapm_clear_walk_input(&card->dapm,
				      &dai->capture_widget->sources);
	}
1152 1153 1154 1155 1156 1157 1158

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

	return paths;
}

1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
/*
 * 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;

1172
	soc_widget_update_bits_locked(w, -(w->reg + 1),
1173 1174 1175 1176
			    w->mask << w->shift, val << w->shift);

	return 0;
}
1177
EXPORT_SYMBOL_GPL(dapm_reg_event);
1178

1179 1180 1181 1182 1183 1184
/*
 * Handler for regulator supply widget.
 */
int dapm_regulator_event(struct snd_soc_dapm_widget *w,
		   struct snd_kcontrol *kcontrol, int event)
{
1185 1186
	int ret;

1187 1188
	soc_dapm_async_complete(w->dapm);

1189
	if (SND_SOC_DAPM_EVENT_ON(event)) {
1190
		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
1191
			ret = regulator_allow_bypass(w->regulator, false);
1192 1193
			if (ret != 0)
				dev_warn(w->dapm->dev,
1194
					 "ASoC: Failed to unbypass %s: %d\n",
1195 1196 1197
					 w->name, ret);
		}

1198
		return regulator_enable(w->regulator);
1199
	} else {
1200
		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
1201
			ret = regulator_allow_bypass(w->regulator, true);
1202 1203
			if (ret != 0)
				dev_warn(w->dapm->dev,
1204
					 "ASoC: Failed to bypass %s: %d\n",
1205 1206 1207
					 w->name, ret);
		}

1208
		return regulator_disable_deferred(w->regulator, w->shift);
1209
	}
1210 1211 1212
}
EXPORT_SYMBOL_GPL(dapm_regulator_event);

1213 1214 1215 1216 1217 1218 1219 1220 1221
/*
 * 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;

1222 1223
	soc_dapm_async_complete(w->dapm);

1224
#ifdef CONFIG_HAVE_CLK
1225
	if (SND_SOC_DAPM_EVENT_ON(event)) {
1226
		return clk_prepare_enable(w->clk);
1227
	} else {
1228
		clk_disable_unprepare(w->clk);
1229 1230
		return 0;
	}
1231
#endif
1232
	return 0;
1233 1234 1235
}
EXPORT_SYMBOL_GPL(dapm_clock_event);

1236 1237
static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
{
1238 1239 1240
	if (w->power_checked)
		return w->new_power;

1241
	if (w->force)
1242
		w->new_power = 1;
1243
	else
1244 1245 1246 1247 1248
		w->new_power = w->power_check(w);

	w->power_checked = true;

	return w->new_power;
1249 1250
}

1251 1252 1253 1254 1255 1256
/* Generic check to see if a widget should be powered.
 */
static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
{
	int in, out;

1257 1258
	DAPM_UPDATE_STAT(w, power_checks);

1259
	in = is_connected_input_ep(w, NULL);
1260
	dapm_clear_walk_input(w->dapm, &w->sources);
1261
	out = is_connected_output_ep(w, NULL);
1262
	dapm_clear_walk_output(w->dapm, &w->sinks);
1263 1264 1265
	return out != 0 && in != 0;
}

1266 1267 1268 1269 1270
/* Check to see if an ADC has power */
static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
{
	int in;

1271 1272
	DAPM_UPDATE_STAT(w, power_checks);

1273
	if (w->active) {
1274
		in = is_connected_input_ep(w, NULL);
1275
		dapm_clear_walk_input(w->dapm, &w->sources);
1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
		return in != 0;
	} else {
		return dapm_generic_check_power(w);
	}
}

/* Check to see if a DAC has power */
static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
{
	int out;

1287 1288
	DAPM_UPDATE_STAT(w, power_checks);

1289
	if (w->active) {
1290
		out = is_connected_output_ep(w, NULL);
1291
		dapm_clear_walk_output(w->dapm, &w->sinks);
1292 1293 1294 1295 1296 1297
		return out != 0;
	} else {
		return dapm_generic_check_power(w);
	}
}

1298 1299 1300 1301 1302
/* 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;

1303 1304
	DAPM_UPDATE_STAT(w, power_checks);

1305 1306
	/* Check if one of our outputs is connected */
	list_for_each_entry(path, &w->sinks, list_source) {
1307 1308
		DAPM_UPDATE_STAT(w, neighbour_checks);

1309 1310 1311
		if (path->weak)
			continue;

1312 1313 1314 1315
		if (path->connected &&
		    !path->connected(path->source, path->sink))
			continue;

1316 1317 1318
		if (!path->sink)
			continue;

1319 1320
		if (dapm_widget_power_check(path->sink))
			return 1;
1321 1322
	}

1323
	return 0;
1324 1325
}

1326 1327 1328 1329 1330
static int dapm_always_on_check_power(struct snd_soc_dapm_widget *w)
{
	return 1;
}

1331 1332
static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
			    struct snd_soc_dapm_widget *b,
1333
			    bool power_up)
1334
{
1335 1336 1337 1338 1339 1340 1341
	int *sort;

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

1342 1343
	if (sort[a->id] != sort[b->id])
		return sort[a->id] - sort[b->id];
1344 1345 1346 1347 1348 1349
	if (a->subseq != b->subseq) {
		if (power_up)
			return a->subseq - b->subseq;
		else
			return b->subseq - a->subseq;
	}
1350 1351
	if (a->reg != b->reg)
		return a->reg - b->reg;
1352 1353
	if (a->dapm != b->dapm)
		return (unsigned long)a->dapm - (unsigned long)b->dapm;
1354

1355 1356
	return 0;
}
1357

1358 1359 1360
/* 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,
1361
			    bool power_up)
1362 1363 1364 1365
{
	struct snd_soc_dapm_widget *w;

	list_for_each_entry(w, list, power_list)
1366
		if (dapm_seq_compare(new_widget, w, power_up) < 0) {
1367 1368 1369 1370 1371 1372 1373
			list_add_tail(&new_widget->power_list, &w->power_list);
			return;
		}

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

1374
static void dapm_seq_check_event(struct snd_soc_card *card,
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396
				 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;
1397 1398 1399 1400 1401 1402 1403 1404
	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;
1405
	default:
T
Takashi Iwai 已提交
1406
		WARN(1, "Unknown event %d\n", event);
1407 1408 1409
		return;
	}

1410
	if (w->new_power != power)
1411 1412 1413
		return;

	if (w->event && (w->event_flags & event)) {
1414
		pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
1415
			w->name, ev_name);
1416
		soc_dapm_async_complete(w->dapm);
M
Mark Brown 已提交
1417
		trace_snd_soc_dapm_widget_event_start(w, event);
1418
		ret = w->event(w, NULL, event);
M
Mark Brown 已提交
1419
		trace_snd_soc_dapm_widget_event_done(w, event);
1420
		if (ret < 0)
1421
			dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n",
1422 1423 1424 1425
			       ev_name, w->name, ret);
	}
}

1426
/* Apply the coalesced changes from a DAPM sequence */
1427
static void dapm_seq_run_coalesced(struct snd_soc_card *card,
1428
				   struct list_head *pending)
1429
{
1430
	struct snd_soc_dapm_widget *w;
1431
	int reg;
1432 1433 1434 1435 1436 1437 1438
	unsigned int value = 0;
	unsigned int mask = 0;

	reg = list_first_entry(pending, struct snd_soc_dapm_widget,
			       power_list)->reg;

	list_for_each_entry(w, pending, power_list) {
1439
		WARN_ON(reg != w->reg);
1440
		w->power = w->new_power;
1441

1442 1443 1444
		mask |= w->mask << w->shift;
		if (w->power)
			value |= w->on_val << w->shift;
1445
		else
1446
			value |= w->off_val << w->shift;
1447

1448
		pop_dbg(w->dapm->dev, card->pop_time,
1449 1450
			"pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
			w->name, reg, value, mask);
1451

1452
		/* Check for events */
1453 1454
		dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMU);
		dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMD);
1455 1456 1457
	}

	if (reg >= 0) {
1458 1459 1460 1461 1462 1463
		/* Any widget will do, they should all be updating the
		 * same register.
		 */
		w = list_first_entry(pending, struct snd_soc_dapm_widget,
				     power_list);

1464
		pop_dbg(w->dapm->dev, card->pop_time,
1465
			"pop test : Applying 0x%x/0x%x to %x in %dms\n",
1466 1467
			value, mask, reg, card->pop_time);
		pop_wait(card->pop_time);
1468
		soc_widget_update_bits_locked(w, reg, mask, value);
1469 1470
	}

1471
	list_for_each_entry(w, pending, power_list) {
1472 1473
		dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMU);
		dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMD);
1474
	}
1475
}
1476

1477 1478 1479 1480 1481 1482 1483 1484
/* 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.
 */
1485 1486
static void dapm_seq_run(struct snd_soc_card *card,
	struct list_head *list, int event, bool power_up)
1487 1488
{
	struct snd_soc_dapm_widget *w, *n;
1489
	struct snd_soc_dapm_context *d;
1490 1491
	LIST_HEAD(pending);
	int cur_sort = -1;
1492
	int cur_subseq = -1;
1493
	int cur_reg = SND_SOC_NOPM;
1494
	struct snd_soc_dapm_context *cur_dapm = NULL;
1495
	int ret, i;
1496 1497 1498 1499 1500 1501
	int *sort;

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

1503 1504 1505 1506
	list_for_each_entry_safe(w, n, list, power_list) {
		ret = 0;

		/* Do we need to apply any queued changes? */
1507
		if (sort[w->id] != cur_sort || w->reg != cur_reg ||
1508
		    w->dapm != cur_dapm || w->subseq != cur_subseq) {
1509
			if (!list_empty(&pending))
1510
				dapm_seq_run_coalesced(card, &pending);
1511

1512 1513 1514 1515
			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,
1516 1517
								       i,
								       cur_subseq);
1518 1519
			}

1520 1521 1522
			if (cur_dapm && w->dapm != cur_dapm)
				soc_dapm_async_complete(cur_dapm);

1523 1524
			INIT_LIST_HEAD(&pending);
			cur_sort = -1;
1525
			cur_subseq = INT_MIN;
1526
			cur_reg = SND_SOC_NOPM;
1527
			cur_dapm = NULL;
1528 1529
		}

1530 1531 1532
		switch (w->id) {
		case snd_soc_dapm_pre:
			if (!w->event)
1533 1534
				list_for_each_entry_safe_continue(w, n, list,
								  power_list);
1535

1536
			if (event == SND_SOC_DAPM_STREAM_START)
1537 1538
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_PRE_PMU);
1539
			else if (event == SND_SOC_DAPM_STREAM_STOP)
1540 1541 1542 1543 1544 1545
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_PRE_PMD);
			break;

		case snd_soc_dapm_post:
			if (!w->event)
1546 1547
				list_for_each_entry_safe_continue(w, n, list,
								  power_list);
1548

1549
			if (event == SND_SOC_DAPM_STREAM_START)
1550 1551
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_POST_PMU);
1552
			else if (event == SND_SOC_DAPM_STREAM_STOP)
1553 1554 1555 1556
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_POST_PMD);
			break;

1557
		default:
1558 1559
			/* Queue it up for application */
			cur_sort = sort[w->id];
1560
			cur_subseq = w->subseq;
1561
			cur_reg = w->reg;
1562
			cur_dapm = w->dapm;
1563 1564
			list_move(&w->power_list, &pending);
			break;
1565
		}
1566 1567

		if (ret < 0)
1568
			dev_err(w->dapm->dev,
1569
				"ASoC: Failed to apply widget power: %d\n", ret);
1570
	}
1571 1572

	if (!list_empty(&pending))
1573
		dapm_seq_run_coalesced(card, &pending);
1574 1575 1576 1577 1578

	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,
1579
						       i, cur_subseq);
1580
	}
1581 1582 1583 1584

	list_for_each_entry(d, &card->dapm_list, list) {
		soc_dapm_async_complete(d);
	}
1585 1586
}

1587
static void dapm_widget_update(struct snd_soc_card *card)
1588
{
1589
	struct snd_soc_dapm_update *update = card->update;
1590 1591 1592
	struct snd_soc_dapm_widget_list *wlist;
	struct snd_soc_dapm_widget *w = NULL;
	unsigned int wi;
1593 1594
	int ret;

1595
	if (!update || !dapm_kcontrol_is_powered(update->kcontrol))
1596 1597
		return;

1598
	wlist = dapm_kcontrol_get_wlist(update->kcontrol);
1599

1600 1601 1602 1603 1604 1605
	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)
1606
				dev_err(w->dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",
1607 1608
					   w->name, ret);
		}
1609 1610
	}

1611 1612 1613
	if (!w)
		return;

1614
	ret = soc_widget_update_bits_locked(w, update->reg, update->mask,
1615 1616
				  update->val);
	if (ret < 0)
1617
		dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",
1618
			w->name, ret);
1619

1620 1621 1622 1623 1624 1625
	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)
1626
				dev_err(w->dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",
1627 1628
					   w->name, ret);
		}
1629 1630 1631
	}
}

1632 1633 1634 1635 1636 1637 1638 1639
/* 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;

1640 1641 1642
	/* If we're off and we're not supposed to be go into STANDBY */
	if (d->bias_level == SND_SOC_BIAS_OFF &&
	    d->target_bias_level != SND_SOC_BIAS_OFF) {
1643 1644 1645
		if (d->dev)
			pm_runtime_get_sync(d->dev);

1646 1647 1648
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
		if (ret != 0)
			dev_err(d->dev,
1649
				"ASoC: Failed to turn on bias: %d\n", ret);
1650 1651
	}

1652 1653
	/* Prepare for a STADDBY->ON or ON->STANDBY transition */
	if (d->bias_level != d->target_bias_level) {
1654 1655 1656
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);
		if (ret != 0)
			dev_err(d->dev,
1657
				"ASoC: Failed to prepare bias: %d\n", ret);
1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669
	}
}

/* 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 */
1670 1671 1672
	if (d->bias_level == SND_SOC_BIAS_PREPARE &&
	    (d->target_bias_level == SND_SOC_BIAS_STANDBY ||
	     d->target_bias_level == SND_SOC_BIAS_OFF)) {
1673 1674
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
		if (ret != 0)
1675
			dev_err(d->dev, "ASoC: Failed to apply standby bias: %d\n",
1676 1677
				ret);
	}
1678

1679
	/* If we're in standby and can support bias off then do that */
1680 1681
	if (d->bias_level == SND_SOC_BIAS_STANDBY &&
	    d->target_bias_level == SND_SOC_BIAS_OFF) {
1682 1683
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
		if (ret != 0)
1684 1685
			dev_err(d->dev, "ASoC: Failed to turn off bias: %d\n",
				ret);
1686 1687

		if (d->dev)
1688
			pm_runtime_put(d->dev);
1689 1690 1691
	}

	/* If we just powered up then move to active bias */
1692 1693
	if (d->bias_level == SND_SOC_BIAS_PREPARE &&
	    d->target_bias_level == SND_SOC_BIAS_ON) {
1694 1695
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON);
		if (ret != 0)
1696
			dev_err(d->dev, "ASoC: Failed to apply active bias: %d\n",
1697 1698 1699
				ret);
	}
}
1700

1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712
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)
1713
		dapm_mark_dirty(peer, "peer state change");
1714 1715
}

1716 1717 1718 1719
static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
				  struct list_head *up_list,
				  struct list_head *down_list)
{
1720 1721
	struct snd_soc_dapm_path *path;

1722 1723 1724 1725 1726
	if (w->power == power)
		return;

	trace_snd_soc_dapm_widget_power(w, power);

1727
	/* If we changed our power state perhaps our neigbours changed
1728
	 * also.
1729 1730 1731
	 */
	list_for_each_entry(path, &w->sources, list_sink) {
		if (path->source) {
1732 1733
			dapm_widget_set_peer_power(path->source, power,
						   path->connect);
1734 1735
		}
	}
1736 1737
	switch (w->id) {
	case snd_soc_dapm_supply:
1738
	case snd_soc_dapm_regulator_supply:
1739
	case snd_soc_dapm_clock_supply:
1740
	case snd_soc_dapm_kcontrol:
1741 1742 1743 1744 1745 1746 1747 1748
		/* Supplies can't affect their outputs, only their inputs */
		break;
	default:
		list_for_each_entry(path, &w->sinks, list_source) {
			if (path->sink) {
				dapm_widget_set_peer_power(path->sink, power,
							   path->connect);
			}
1749
		}
1750
		break;
1751 1752
	}

1753 1754 1755 1756 1757 1758
	if (power)
		dapm_seq_insert(w, up_list, true);
	else
		dapm_seq_insert(w, down_list, false);
}

1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773
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:
1774
		power = dapm_widget_power_check(w);
1775

1776
		dapm_widget_set_power(w, power, up_list, down_list);
1777 1778 1779 1780
		break;
	}
}

1781 1782 1783 1784 1785 1786 1787 1788 1789
/*
 * 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.
 *  o Input Pin to ADC.
 *  o Input pin to Output pin (bypass, sidetone)
 *  o DAC to ADC (loopback).
 */
1790
static int dapm_power_widgets(struct snd_soc_card *card, int event)
1791 1792
{
	struct snd_soc_dapm_widget *w;
1793
	struct snd_soc_dapm_context *d;
1794 1795
	LIST_HEAD(up_list);
	LIST_HEAD(down_list);
1796
	ASYNC_DOMAIN_EXCLUSIVE(async_domain);
1797
	enum snd_soc_bias_level bias;
1798

M
Mark Brown 已提交
1799 1800
	trace_snd_soc_dapm_start(card);

1801
	list_for_each_entry(d, &card->dapm_list, list) {
1802 1803 1804 1805
		if (d->idle_bias_off)
			d->target_bias_level = SND_SOC_BIAS_OFF;
		else
			d->target_bias_level = SND_SOC_BIAS_STANDBY;
1806
	}
1807

1808
	dapm_reset(card);
1809

1810
	/* Check which widgets we need to power and store them in
1811 1812 1813 1814
	 * 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.
1815
	 */
1816
	list_for_each_entry(w, &card->dapm_dirty, dirty) {
1817
		dapm_power_one_widget(w, &up_list, &down_list);
1818 1819
	}

1820
	list_for_each_entry(w, &card->widgets, list) {
1821 1822 1823 1824 1825 1826 1827 1828 1829
		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;
		}
1830

1831
		if (w->new_power) {
1832 1833 1834 1835 1836
			d = w->dapm;

			/* Supplies and micbiases only bring the
			 * context up to STANDBY as unless something
			 * else is active and passing audio they
1837 1838 1839
			 * generally don't require full power.  Signal
			 * generators are virtual pins and have no
			 * power impact themselves.
1840 1841
			 */
			switch (w->id) {
1842
			case snd_soc_dapm_siggen:
1843
			case snd_soc_dapm_vmid:
1844
				break;
1845
			case snd_soc_dapm_supply:
1846
			case snd_soc_dapm_regulator_supply:
1847
			case snd_soc_dapm_clock_supply:
1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859
			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;
			}
		}

	}

1860 1861 1862
	/* Force all contexts in the card to the same bias state if
	 * they're not ground referenced.
	 */
1863
	bias = SND_SOC_BIAS_OFF;
1864
	list_for_each_entry(d, &card->dapm_list, list)
1865 1866
		if (d->target_bias_level > bias)
			bias = d->target_bias_level;
1867
	list_for_each_entry(d, &card->dapm_list, list)
1868 1869
		if (!d->idle_bias_off)
			d->target_bias_level = bias;
1870

1871
	trace_snd_soc_dapm_walk_done(card);
1872

1873
	/* Run all the bias changes in parallel */
1874
	list_for_each_entry(d, &card->dapm_list, list)
1875 1876 1877
		async_schedule_domain(dapm_pre_sequence_async, d,
					&async_domain);
	async_synchronize_full_domain(&async_domain);
1878

1879
	list_for_each_entry(w, &down_list, power_list) {
1880
		dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMD);
1881 1882
	}

1883
	list_for_each_entry(w, &up_list, power_list) {
1884
		dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMU);
1885 1886
	}

1887
	/* Power down widgets first; try to avoid amplifying pops. */
1888
	dapm_seq_run(card, &down_list, event, false);
1889

1890
	dapm_widget_update(card);
1891

1892
	/* Now power up. */
1893
	dapm_seq_run(card, &up_list, event, true);
1894

1895
	/* Run all the bias changes in parallel */
1896
	list_for_each_entry(d, &card->dapm_list, list)
1897 1898 1899
		async_schedule_domain(dapm_post_sequence_async, d,
					&async_domain);
	async_synchronize_full_domain(&async_domain);
1900

1901 1902 1903 1904 1905 1906
	/* 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);
	}

1907
	pop_dbg(card->dev, card->pop_time,
1908
		"DAPM sequencing finished, waiting %dms\n", card->pop_time);
1909
	pop_wait(card->pop_time);
1910

M
Mark Brown 已提交
1911 1912
	trace_snd_soc_dapm_done(card);

1913
	return 0;
1914 1915
}

1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930
#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;
	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;

1931
	in = is_connected_input_ep(w, NULL);
1932
	dapm_clear_walk_input(w->dapm, &w->sources);
1933
	out = is_connected_output_ep(w, NULL);
1934
	dapm_clear_walk_output(w->dapm, &w->sinks);
1935

1936 1937 1938
	ret = snprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
		       w->name, w->power ? "On" : "Off",
		       w->force ? " (forced)" : "", in, out);
1939

1940 1941
	if (w->reg >= 0)
		ret += snprintf(buf + ret, PAGE_SIZE - ret,
1942 1943
				" - R%d(0x%x) mask 0x%x",
				w->reg, w->reg, w->mask << w->shift);
1944 1945 1946

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

1947 1948 1949 1950
	if (w->sname)
		ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
				w->sname,
				w->active ? "active" : "inactive");
1951 1952

	list_for_each_entry(p, &w->sources, list_sink) {
1953
		if (p->connected && !p->connected(w, p->source))
1954 1955
			continue;

1956 1957
		if (p->connect)
			ret += snprintf(buf + ret, PAGE_SIZE - ret,
1958
					" in  \"%s\" \"%s\"\n",
1959 1960 1961 1962
					p->name ? p->name : "static",
					p->source->name);
	}
	list_for_each_entry(p, &w->sinks, list_source) {
1963 1964 1965
		if (p->connected && !p->connected(w, p->sink))
			continue;

1966 1967
		if (p->connect)
			ret += snprintf(buf + ret, PAGE_SIZE - ret,
1968
					" out \"%s\" \"%s\"\n",
1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979
					p->name ? p->name : "static",
					p->sink->name);
	}

	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);

	kfree(buf);
	return ret;
}

static const struct file_operations dapm_widget_power_fops = {
1980
	.open = simple_open,
1981
	.read = dapm_widget_power_read_file,
1982
	.llseek = default_llseek,
1983 1984
};

1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004
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 已提交
2005
		WARN(1, "Unknown bias_level %d\n", dapm->bias_level);
2006 2007 2008 2009 2010 2011 2012 2013 2014
		level = "Unknown\n";
		break;
	}

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

static const struct file_operations dapm_bias_fops = {
2015
	.open = simple_open,
2016 2017 2018 2019
	.read = dapm_bias_read_file,
	.llseek = default_llseek,
};

2020 2021
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
	struct dentry *parent)
2022 2023 2024
{
	struct dentry *d;

2025 2026 2027
	dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);

	if (!dapm->debugfs_dapm) {
2028
		dev_warn(dapm->dev,
2029
		       "ASoC: Failed to create DAPM debugfs directory\n");
2030
		return;
2031
	}
2032

2033 2034 2035 2036 2037 2038
	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");
2039
}
2040

2041 2042 2043 2044
static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
{
	struct snd_soc_dapm_context *dapm = w->dapm;
	struct dentry *d;
2045

2046 2047 2048 2049 2050 2051 2052 2053 2054 2055
	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);
2056
}
2057

2058 2059 2060 2061 2062
static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
{
	debugfs_remove_recursive(dapm->debugfs_dapm);
}

2063
#else
2064 2065
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
	struct dentry *parent)
2066 2067
{
}
2068 2069 2070 2071 2072

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

2073 2074 2075 2076
static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
{
}

2077 2078
#endif

2079
/* test and update the power status of a mux widget */
2080
static int soc_dapm_mux_update_power(struct snd_soc_card *card,
2081
				 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
2082 2083 2084 2085 2086
{
	struct snd_soc_dapm_path *path;
	int found = 0;

	/* find dapm widget path assoc with kcontrol */
2087
	dapm_kcontrol_for_each_path(path, kcontrol) {
2088
		if (!path->name || !e->texts[mux])
2089 2090 2091 2092
			continue;

		found = 1;
		/* we now need to match the string in the enum to the path */
2093
		if (!(strcmp(path->name, e->texts[mux]))) {
2094
			path->connect = 1; /* new connection */
2095
			dapm_mark_dirty(path->source, "mux connection");
2096 2097
		} else {
			if (path->connect)
2098 2099
				dapm_mark_dirty(path->source,
						"mux disconnection");
2100
			path->connect = 0; /* old connection must be powered down */
2101
		}
2102
		dapm_mark_dirty(path->sink, "mux change");
2103 2104
	}

2105
	if (found)
2106
		dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
2107

2108
	return found;
2109
}
2110

2111
int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
2112 2113
	struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
	struct snd_soc_dapm_update *update)
2114
{
2115
	struct snd_soc_card *card = dapm->card;
2116 2117
	int ret;

2118
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2119
	card->update = update;
2120
	ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
2121
	card->update = NULL;
2122
	mutex_unlock(&card->dapm_mutex);
2123
	if (ret > 0)
2124
		soc_dpcm_runtime_update(card);
2125 2126
	return ret;
}
2127
EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
2128

2129
/* test and update the power status of a mixer or switch widget */
2130
static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
2131
				   struct snd_kcontrol *kcontrol, int connect)
2132 2133 2134 2135 2136
{
	struct snd_soc_dapm_path *path;
	int found = 0;

	/* find dapm widget path assoc with kcontrol */
2137
	dapm_kcontrol_for_each_path(path, kcontrol) {
2138
		found = 1;
2139
		path->connect = connect;
2140
		dapm_mark_dirty(path->source, "mixer connection");
2141
		dapm_mark_dirty(path->sink, "mixer update");
2142 2143
	}

2144
	if (found)
2145
		dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
2146

2147
	return found;
2148
}
2149

2150
int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
2151 2152
	struct snd_kcontrol *kcontrol, int connect,
	struct snd_soc_dapm_update *update)
2153
{
2154
	struct snd_soc_card *card = dapm->card;
2155 2156
	int ret;

2157
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2158
	card->update = update;
2159
	ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
2160
	card->update = NULL;
2161
	mutex_unlock(&card->dapm_mutex);
2162
	if (ret > 0)
2163
		soc_dpcm_runtime_update(card);
2164 2165
	return ret;
}
2166
EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
2167 2168 2169 2170 2171

/* show dapm widget status in sys fs */
static ssize_t dapm_widget_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{
2172
	struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
2173
	struct snd_soc_codec *codec =rtd->codec;
2174 2175 2176 2177
	struct snd_soc_dapm_widget *w;
	int count = 0;
	char *state = "not set";

2178 2179 2180
	list_for_each_entry(w, &codec->card->widgets, list) {
		if (w->dapm != &codec->dapm)
			continue;
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191

		/* only display widgets that burnm power */
		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:
2192
		case snd_soc_dapm_out_drv:
2193
		case snd_soc_dapm_mixer:
2194
		case snd_soc_dapm_mixer_named_ctl:
2195
		case snd_soc_dapm_supply:
2196
		case snd_soc_dapm_regulator_supply:
2197
		case snd_soc_dapm_clock_supply:
2198 2199 2200 2201 2202 2203 2204 2205 2206
			if (w->name)
				count += sprintf(buf + count, "%s: %s\n",
					w->name, w->power ? "On":"Off");
		break;
		default:
		break;
		}
	}

L
Liam Girdwood 已提交
2207
	switch (codec->dapm.bias_level) {
2208 2209
	case SND_SOC_BIAS_ON:
		state = "On";
2210
		break;
2211 2212
	case SND_SOC_BIAS_PREPARE:
		state = "Prepare";
2213
		break;
2214 2215
	case SND_SOC_BIAS_STANDBY:
		state = "Standby";
2216
		break;
2217 2218
	case SND_SOC_BIAS_OFF:
		state = "Off";
2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229
		break;
	}
	count += sprintf(buf + count, "PM State: %s\n", state);

	return count;
}

static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);

int snd_soc_dapm_sys_add(struct device *dev)
{
2230
	return device_create_file(dev, &dev_attr_dapm_widget);
2231 2232 2233 2234
}

static void snd_soc_dapm_sys_remove(struct device *dev)
{
2235
	device_remove_file(dev, &dev_attr_dapm_widget);
2236 2237
}

2238 2239 2240 2241
static void dapm_free_path(struct snd_soc_dapm_path *path)
{
	list_del(&path->list_sink);
	list_del(&path->list_source);
2242
	list_del(&path->list_kcontrol);
2243 2244 2245 2246
	list_del(&path->list);
	kfree(path);
}

2247
/* free all dapm widgets and resources */
L
Liam Girdwood 已提交
2248
static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
2249 2250 2251 2252
{
	struct snd_soc_dapm_widget *w, *next_w;
	struct snd_soc_dapm_path *p, *next_p;

2253 2254 2255
	list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
		if (w->dapm != dapm)
			continue;
2256
		list_del(&w->list);
2257 2258 2259 2260 2261
		/*
		 * 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.
		 */
2262 2263 2264 2265 2266 2267
		list_for_each_entry_safe(p, next_p, &w->sources, list_sink)
			dapm_free_path(p);

		list_for_each_entry_safe(p, next_p, &w->sinks, list_source)
			dapm_free_path(p);

2268
		kfree(w->kcontrols);
2269
		kfree(w->name);
2270 2271 2272 2273
		kfree(w);
	}
}

2274 2275 2276
static struct snd_soc_dapm_widget *dapm_find_widget(
			struct snd_soc_dapm_context *dapm, const char *pin,
			bool search_other_contexts)
2277 2278
{
	struct snd_soc_dapm_widget *w;
2279
	struct snd_soc_dapm_widget *fallback = NULL;
2280

2281
	list_for_each_entry(w, &dapm->card->widgets, list) {
2282
		if (!strcmp(w->name, pin)) {
2283 2284 2285 2286
			if (w->dapm == dapm)
				return w;
			else
				fallback = w;
2287 2288 2289
		}
	}

2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301
	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);

	if (!w) {
2302
		dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin);
2303
		return -EINVAL;
2304 2305
	}

2306 2307 2308
	if (w->connected != status)
		dapm_mark_dirty(w, "pin configuration");

2309 2310 2311 2312 2313
	w->connected = status;
	if (status == 0)
		w->force = 0;

	return 0;
2314 2315
}

2316
/**
2317
 * snd_soc_dapm_sync_unlocked - scan and power dapm paths
L
Liam Girdwood 已提交
2318
 * @dapm: DAPM context
2319 2320 2321 2322
 *
 * Walks all dapm audio paths and powers widgets according to their
 * stream or path usage.
 *
2323 2324
 * Requires external locking.
 *
2325 2326
 * Returns 0 for success.
 */
2327
int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm)
2328
{
2329 2330 2331 2332 2333 2334 2335
	/*
	 * Suppress early reports (eg, jacks syncing their state) to avoid
	 * silly DAPM runs during card startup.
	 */
	if (!dapm->card || !dapm->card->instantiated)
		return 0;

2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352
	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;

2353
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2354
	ret = snd_soc_dapm_sync_unlocked(dapm);
2355 2356
	mutex_unlock(&dapm->card->dapm_mutex);
	return ret;
2357
}
2358
EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
2359

2360 2361 2362 2363 2364
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))
2365 2366
{
	struct snd_soc_dapm_path *path;
2367
	int ret;
2368 2369 2370 2371 2372 2373 2374

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

	path->source = wsource;
	path->sink = wsink;
2375
	path->connected = connected;
2376
	INIT_LIST_HEAD(&path->list);
2377
	INIT_LIST_HEAD(&path->list_kcontrol);
2378 2379 2380 2381 2382 2383 2384
	INIT_LIST_HEAD(&path->list_source);
	INIT_LIST_HEAD(&path->list_sink);

	/* check for external widgets */
	if (wsink->id == snd_soc_dapm_input) {
		if (wsource->id == snd_soc_dapm_micbias ||
			wsource->id == snd_soc_dapm_mic ||
2385 2386
			wsource->id == snd_soc_dapm_line ||
			wsource->id == snd_soc_dapm_output)
2387 2388 2389 2390 2391
			wsink->ext = 1;
	}
	if (wsource->id == snd_soc_dapm_output) {
		if (wsink->id == snd_soc_dapm_spk ||
			wsink->id == snd_soc_dapm_hp ||
2392 2393
			wsink->id == snd_soc_dapm_line ||
			wsink->id == snd_soc_dapm_input)
2394 2395 2396
			wsource->ext = 1;
	}

2397 2398 2399
	dapm_mark_dirty(wsource, "Route added");
	dapm_mark_dirty(wsink, "Route added");

2400 2401
	/* connect static paths */
	if (control == NULL) {
2402
		list_add(&path->list, &dapm->card->paths);
2403 2404 2405 2406 2407 2408 2409
		list_add(&path->list_sink, &wsink->sources);
		list_add(&path->list_source, &wsource->sinks);
		path->connect = 1;
		return 0;
	}

	/* connect dynamic paths */
2410
	switch (wsink->id) {
2411 2412 2413
	case snd_soc_dapm_adc:
	case snd_soc_dapm_dac:
	case snd_soc_dapm_pga:
2414
	case snd_soc_dapm_out_drv:
2415 2416
	case snd_soc_dapm_input:
	case snd_soc_dapm_output:
2417
	case snd_soc_dapm_siggen:
2418 2419 2420 2421
	case snd_soc_dapm_micbias:
	case snd_soc_dapm_vmid:
	case snd_soc_dapm_pre:
	case snd_soc_dapm_post:
2422
	case snd_soc_dapm_supply:
2423
	case snd_soc_dapm_regulator_supply:
2424
	case snd_soc_dapm_clock_supply:
2425 2426
	case snd_soc_dapm_aif_in:
	case snd_soc_dapm_aif_out:
2427 2428
	case snd_soc_dapm_dai_in:
	case snd_soc_dapm_dai_out:
2429
	case snd_soc_dapm_dai_link:
2430
	case snd_soc_dapm_kcontrol:
2431
		list_add(&path->list, &dapm->card->paths);
2432 2433 2434 2435 2436
		list_add(&path->list_sink, &wsink->sources);
		list_add(&path->list_source, &wsource->sinks);
		path->connect = 1;
		return 0;
	case snd_soc_dapm_mux:
L
Liam Girdwood 已提交
2437
		ret = dapm_connect_mux(dapm, wsource, wsink, path, control,
2438
			&wsink->kcontrol_news[0]);
2439 2440 2441 2442 2443
		if (ret != 0)
			goto err;
		break;
	case snd_soc_dapm_switch:
	case snd_soc_dapm_mixer:
2444
	case snd_soc_dapm_mixer_named_ctl:
L
Liam Girdwood 已提交
2445
		ret = dapm_connect_mixer(dapm, wsource, wsink, path, control);
2446 2447 2448 2449 2450 2451 2452
		if (ret != 0)
			goto err;
		break;
	case snd_soc_dapm_hp:
	case snd_soc_dapm_mic:
	case snd_soc_dapm_line:
	case snd_soc_dapm_spk:
2453
		list_add(&path->list, &dapm->card->paths);
2454 2455 2456 2457 2458
		list_add(&path->list_sink, &wsink->sources);
		list_add(&path->list_source, &wsource->sinks);
		path->connect = 0;
		return 0;
	}
2459

2460
	return 0;
2461 2462 2463 2464
err:
	kfree(path);
	return ret;
}
2465

2466
static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2467 2468
				  const struct snd_soc_dapm_route *route,
				  unsigned int is_prefixed)
2469 2470 2471 2472 2473 2474 2475 2476 2477
{
	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];
	int ret;

2478
	if (dapm->codec && dapm->codec->name_prefix && !is_prefixed) {
2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529
		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
			 dapm->codec->name_prefix, route->sink);
		sink = prefixed_sink;
		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
			 dapm->codec->name_prefix, route->source);
		source = prefixed_source;
	} else {
		sink = route->sink;
		source = route->source;
	}

	/*
	 * 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;
			if (w->dapm == dapm)
				wsink = w;
			continue;
		}
		if (!wsource && !(strcmp(w->name, source))) {
			wtsource = w;
			if (w->dapm == dapm)
				wsource = w;
		}
	}
	/* 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;
	}

	ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control,
		route->connected);
	if (ret)
		goto err;

	return 0;
2530
err:
2531
	dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n",
2532
		 source, route->control, sink);
2533 2534
	return ret;
}
2535

2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546
static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
				  const struct snd_soc_dapm_route *route)
{
	struct snd_soc_dapm_path *path, *p;
	const char *sink;
	const char *source;
	char prefixed_sink[80];
	char prefixed_source[80];

	if (route->control) {
		dev_err(dapm->dev,
2547
			"ASoC: Removal of routes with controls not supported\n");
2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576
		return -EINVAL;
	}

	if (dapm->codec && dapm->codec->name_prefix) {
		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
			 dapm->codec->name_prefix, route->sink);
		sink = prefixed_sink;
		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
			 dapm->codec->name_prefix, route->source);
		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) {
		dapm_mark_dirty(path->source, "Route removed");
		dapm_mark_dirty(path->sink, "Route removed");

2577
		dapm_free_path(path);
2578
	} else {
2579
		dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n",
2580 2581 2582 2583 2584 2585
			 source, sink);
	}

	return 0;
}

2586 2587
/**
 * snd_soc_dapm_add_routes - Add routes between DAPM widgets
L
Liam Girdwood 已提交
2588
 * @dapm: DAPM context
2589 2590 2591 2592 2593 2594 2595 2596 2597 2598
 * @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 已提交
2599
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
2600 2601
			    const struct snd_soc_dapm_route *route, int num)
{
2602
	int i, r, ret = 0;
2603

2604
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2605
	for (i = 0; i < num; i++) {
2606
		r = snd_soc_dapm_add_route(dapm, route, false);
2607
		if (r < 0) {
2608 2609 2610 2611
			dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n",
				route->source,
				route->control ? route->control : "direct",
				route->sink);
2612
			ret = r;
2613 2614 2615
		}
		route++;
	}
2616
	mutex_unlock(&dapm->card->dapm_mutex);
2617

2618
	return ret;
2619 2620 2621
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);

2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645
/**
 * 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)
{
	int i, ret = 0;

	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
	for (i = 0; i < num; i++) {
		snd_soc_dapm_del_route(dapm, route);
		route++;
	}
	mutex_unlock(&dapm->card->dapm_mutex);

	return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_del_routes);

2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658
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) {
2659
		dev_err(dapm->dev, "ASoC: Unable to find source %s for weak route\n",
2660 2661 2662 2663 2664
			route->source);
		return -ENODEV;
	}

	if (!sink) {
2665
		dev_err(dapm->dev, "ASoC: Unable to find sink %s for weak route\n",
2666 2667 2668 2669 2670
			route->sink);
		return -ENODEV;
	}

	if (route->control || route->connected)
2671
		dev_warn(dapm->dev, "ASoC: Ignoring control for weak route %s->%s\n",
2672 2673 2674 2675 2676 2677 2678 2679 2680 2681
			 route->source, route->sink);

	list_for_each_entry(path, &source->sinks, list_source) {
		if (path->sink == sink) {
			path->weak = 1;
			count++;
		}
	}

	if (count == 0)
2682
		dev_err(dapm->dev, "ASoC: No path found for weak route %s->%s\n",
2683 2684
			route->source, route->sink);
	if (count > 1)
2685
		dev_warn(dapm->dev, "ASoC: %d paths found for weak route %s->%s\n",
2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712
			 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;

2713
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2714 2715 2716 2717 2718 2719
	for (i = 0; i < num; i++) {
		err = snd_soc_dapm_weak_route(dapm, route);
		if (err)
			ret = err;
		route++;
	}
2720
	mutex_unlock(&dapm->card->dapm_mutex);
2721 2722 2723 2724 2725

	return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);

2726 2727
/**
 * snd_soc_dapm_new_widgets - add new dapm widgets
L
Liam Girdwood 已提交
2728
 * @dapm: DAPM context
2729 2730 2731 2732 2733
 *
 * Checks the codec for any new dapm widgets and creates them if found.
 *
 * Returns 0 for success.
 */
2734
int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
2735 2736
{
	struct snd_soc_dapm_widget *w;
2737
	unsigned int val;
2738

2739
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2740

2741
	list_for_each_entry(w, &card->widgets, list)
2742 2743 2744 2745
	{
		if (w->new)
			continue;

2746 2747 2748 2749
		if (w->num_kcontrols) {
			w->kcontrols = kzalloc(w->num_kcontrols *
						sizeof(struct snd_kcontrol *),
						GFP_KERNEL);
2750
			if (!w->kcontrols) {
2751
				mutex_unlock(&card->dapm_mutex);
2752
				return -ENOMEM;
2753
			}
2754 2755
		}

2756 2757 2758
		switch(w->id) {
		case snd_soc_dapm_switch:
		case snd_soc_dapm_mixer:
2759
		case snd_soc_dapm_mixer_named_ctl:
2760
			dapm_new_mixer(w);
2761 2762
			break;
		case snd_soc_dapm_mux:
2763
			dapm_new_mux(w);
2764 2765
			break;
		case snd_soc_dapm_pga:
2766
		case snd_soc_dapm_out_drv:
2767
			dapm_new_pga(w);
2768
			break;
2769
		default:
2770 2771
			break;
		}
2772 2773 2774

		/* Read the initial power state from the device */
		if (w->reg >= 0) {
2775 2776
			soc_widget_read(w, w->reg, &val);
			val = val >> w->shift;
2777 2778
			val &= w->mask;
			if (val == w->on_val)
2779 2780 2781
				w->power = 1;
		}

2782
		w->new = 1;
2783

2784
		dapm_mark_dirty(w, "new widget");
2785
		dapm_debugfs_add_widget(w);
2786 2787
	}

2788 2789
	dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
	mutex_unlock(&card->dapm_mutex);
2790 2791 2792 2793 2794 2795 2796
	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 已提交
2797
 * @ucontrol: control element information
2798 2799 2800 2801 2802 2803 2804 2805
 *
 * 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)
{
2806
	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2807
	struct snd_soc_card *card = codec->card;
2808 2809
	struct soc_mixer_control *mc =
		(struct soc_mixer_control *)kcontrol->private_value;
2810
	int reg = mc->reg;
2811
	unsigned int shift = mc->shift;
2812
	int max = mc->max;
2813
	unsigned int mask = (1 << fls(max)) - 1;
2814
	unsigned int invert = mc->invert;
2815
	unsigned int val;
2816 2817

	if (snd_soc_volsw_is_stereo(mc))
2818
		dev_warn(codec->dapm.dev,
2819
			 "ASoC: Control '%s' is stereo, which is not supported\n",
2820
			 kcontrol->id.name);
2821

2822
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2823
	if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM)
2824 2825 2826 2827 2828
		val = (snd_soc_read(codec, reg) >> shift) & mask;
	else
		val = dapm_kcontrol_get_value(kcontrol);
	mutex_unlock(&card->dapm_mutex);

2829
	if (invert)
2830 2831 2832
		ucontrol->value.integer.value[0] = max - val;
	else
		ucontrol->value.integer.value[0] = val;
2833 2834 2835 2836 2837 2838 2839 2840

	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);

/**
 * snd_soc_dapm_put_volsw - dapm mixer set callback
 * @kcontrol: mixer control
M
Mark Brown 已提交
2841
 * @ucontrol: control element information
2842 2843 2844 2845 2846 2847 2848 2849
 *
 * 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)
{
2850
	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2851
	struct snd_soc_card *card = codec->card;
2852 2853
	struct soc_mixer_control *mc =
		(struct soc_mixer_control *)kcontrol->private_value;
2854
	int reg = mc->reg;
2855
	unsigned int shift = mc->shift;
2856
	int max = mc->max;
2857 2858
	unsigned int mask = (1 << fls(max)) - 1;
	unsigned int invert = mc->invert;
2859
	unsigned int val;
2860 2861
	int connect, change;
	struct snd_soc_dapm_update update;
2862
	int ret = 0;
2863

2864
	if (snd_soc_volsw_is_stereo(mc))
2865
		dev_warn(codec->dapm.dev,
2866
			 "ASoC: Control '%s' is stereo, which is not supported\n",
2867 2868
			 kcontrol->id.name);

2869
	val = (ucontrol->value.integer.value[0] & mask);
2870
	connect = !!val;
2871 2872

	if (invert)
P
Philipp Zabel 已提交
2873
		val = max - val;
2874

2875
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2876

2877
	change = dapm_kcontrol_set_value(kcontrol, val);
2878

2879 2880 2881 2882 2883 2884
	if (reg != SND_SOC_NOPM) {
		mask = mask << shift;
		val = val << shift;

		change = snd_soc_test_bits(codec, reg, mask, val);
	}
2885

2886
	if (change) {
2887 2888 2889 2890 2891
		if (reg != SND_SOC_NOPM) {
			update.kcontrol = kcontrol;
			update.reg = reg;
			update.mask = mask;
			update.val = val;
2892

2893 2894
			card->update = &update;
		}
2895

2896
		ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
2897

2898
		card->update = NULL;
2899 2900
	}

2901
	mutex_unlock(&card->dapm_mutex);
2902 2903 2904 2905

	if (ret > 0)
		soc_dpcm_runtime_update(card);

2906
	return change;
2907 2908 2909 2910 2911 2912
}
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 已提交
2913
 * @ucontrol: control element information
2914 2915 2916 2917 2918 2919 2920 2921
 *
 * 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)
{
2922
	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2923
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2924
	unsigned int reg_val, val;
2925

2926 2927 2928 2929 2930
	if (e->reg != SND_SOC_NOPM)
		reg_val = snd_soc_read(codec, e->reg);
	else
		reg_val = dapm_kcontrol_get_value(kcontrol);

2931 2932 2933 2934 2935 2936 2937
	val = (reg_val >> e->shift_l) & e->mask;
	ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val);
	if (e->shift_l != e->shift_r) {
		val = (reg_val >> e->shift_r) & e->mask;
		val = snd_soc_enum_val_to_item(e, val);
		ucontrol->value.enumerated.item[1] = val;
	}
2938 2939 2940 2941 2942 2943 2944 2945

	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);

/**
 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
 * @kcontrol: mixer control
M
Mark Brown 已提交
2946
 * @ucontrol: control element information
2947 2948 2949 2950 2951 2952 2953 2954
 *
 * Callback to set the value of a dapm enumerated double mixer control.
 *
 * Returns 0 for success.
 */
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
2955
	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2956
	struct snd_soc_card *card = codec->card;
2957
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2958 2959
	unsigned int *item = ucontrol->value.enumerated.item;
	unsigned int val, change;
2960
	unsigned int mask;
2961
	struct snd_soc_dapm_update update;
2962
	int ret = 0;
2963

2964
	if (item[0] >= e->items)
2965
		return -EINVAL;
2966 2967

	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
2968
	mask = e->mask << e->shift_l;
2969
	if (e->shift_l != e->shift_r) {
2970
		if (item[1] > e->items)
2971
			return -EINVAL;
2972
		val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_l;
2973
		mask |= e->mask << e->shift_r;
2974 2975
	}

2976
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2977

2978 2979 2980 2981 2982
	if (e->reg != SND_SOC_NOPM)
		change = snd_soc_test_bits(codec, e->reg, mask, val);
	else
		change = dapm_kcontrol_set_value(kcontrol, val);

2983
	if (change) {
2984 2985 2986 2987 2988 2989 2990
		if (e->reg != SND_SOC_NOPM) {
			update.kcontrol = kcontrol;
			update.reg = e->reg;
			update.mask = mask;
			update.val = val;
			card->update = &update;
		}
2991

2992
		ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e);
2993

2994
		card->update = NULL;
2995
	}
2996

2997
	mutex_unlock(&card->dapm_mutex);
2998 2999 3000 3001

	if (ret > 0)
		soc_dpcm_runtime_update(card);

3002
	return change;
3003 3004 3005
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);

3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034
/**
 * 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)
{
3035
	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3036 3037
	const char *pin = (const char *)kcontrol->private_value;

3038
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3039 3040

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

3043
	mutex_unlock(&card->dapm_mutex);
3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057

	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)
{
3058
	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3059 3060 3061
	const char *pin = (const char *)kcontrol->private_value;

	if (ucontrol->value.integer.value[0])
3062
		snd_soc_dapm_enable_pin(&card->dapm, pin);
3063
	else
3064
		snd_soc_dapm_disable_pin(&card->dapm, pin);
3065

3066
	snd_soc_dapm_sync(&card->dapm);
3067 3068 3069 3070
	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);

3071 3072 3073
static struct snd_soc_dapm_widget *
snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
			 const struct snd_soc_dapm_widget *widget)
3074 3075
{
	struct snd_soc_dapm_widget *w;
3076
	int ret;
3077 3078

	if ((w = dapm_cnew_widget(widget)) == NULL)
3079
		return NULL;
3080

3081 3082
	switch (w->id) {
	case snd_soc_dapm_regulator_supply:
3083 3084 3085
		w->regulator = devm_regulator_get(dapm->dev, w->name);
		if (IS_ERR(w->regulator)) {
			ret = PTR_ERR(w->regulator);
3086
			dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
3087
				w->name, ret);
3088
			return NULL;
3089
		}
3090

3091
		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
3092 3093 3094
			ret = regulator_allow_bypass(w->regulator, true);
			if (ret != 0)
				dev_warn(w->dapm->dev,
3095
					 "ASoC: Failed to bypass %s: %d\n",
3096 3097
					 w->name, ret);
		}
3098
		break;
3099
	case snd_soc_dapm_clock_supply:
3100
#ifdef CONFIG_CLKDEV_LOOKUP
M
Mark Brown 已提交
3101
		w->clk = devm_clk_get(dapm->dev, w->name);
3102 3103
		if (IS_ERR(w->clk)) {
			ret = PTR_ERR(w->clk);
3104
			dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
3105 3106 3107
				w->name, ret);
			return NULL;
		}
3108 3109 3110
#else
		return NULL;
#endif
3111
		break;
3112 3113 3114
	default:
		break;
	}
3115

3116
	if (dapm->codec && dapm->codec->name_prefix)
3117 3118 3119 3120 3121
		w->name = kasprintf(GFP_KERNEL, "%s %s",
			dapm->codec->name_prefix, widget->name);
	else
		w->name = kasprintf(GFP_KERNEL, "%s", widget->name);

3122 3123
	if (w->name == NULL) {
		kfree(w);
3124
		return NULL;
3125 3126
	}

3127 3128 3129 3130 3131 3132 3133 3134 3135
	switch (w->id) {
	case snd_soc_dapm_switch:
	case snd_soc_dapm_mixer:
	case snd_soc_dapm_mixer_named_ctl:
		w->power_check = dapm_generic_check_power;
		break;
	case snd_soc_dapm_mux:
		w->power_check = dapm_generic_check_power;
		break;
3136
	case snd_soc_dapm_dai_out:
3137 3138
		w->power_check = dapm_adc_check_power;
		break;
3139
	case snd_soc_dapm_dai_in:
3140 3141
		w->power_check = dapm_dac_check_power;
		break;
3142 3143 3144 3145
	case snd_soc_dapm_adc:
	case snd_soc_dapm_aif_out:
	case snd_soc_dapm_dac:
	case snd_soc_dapm_aif_in:
3146 3147 3148 3149 3150 3151 3152 3153 3154
	case snd_soc_dapm_pga:
	case snd_soc_dapm_out_drv:
	case snd_soc_dapm_input:
	case snd_soc_dapm_output:
	case snd_soc_dapm_micbias:
	case snd_soc_dapm_spk:
	case snd_soc_dapm_hp:
	case snd_soc_dapm_mic:
	case snd_soc_dapm_line:
3155
	case snd_soc_dapm_dai_link:
3156 3157 3158
		w->power_check = dapm_generic_check_power;
		break;
	case snd_soc_dapm_supply:
3159
	case snd_soc_dapm_regulator_supply:
3160
	case snd_soc_dapm_clock_supply:
3161
	case snd_soc_dapm_kcontrol:
3162 3163 3164 3165 3166 3167 3168
		w->power_check = dapm_supply_check_power;
		break;
	default:
		w->power_check = dapm_always_on_check_power;
		break;
	}

L
Liam Girdwood 已提交
3169 3170
	w->dapm = dapm;
	w->codec = dapm->codec;
3171
	w->platform = dapm->platform;
3172 3173 3174
	INIT_LIST_HEAD(&w->sources);
	INIT_LIST_HEAD(&w->sinks);
	INIT_LIST_HEAD(&w->list);
3175
	INIT_LIST_HEAD(&w->dirty);
3176
	list_add(&w->list, &dapm->card->widgets);
3177 3178 3179

	/* machine layer set ups unconnected pins and insertions */
	w->connected = 1;
3180
	return w;
3181 3182
}

3183 3184
/**
 * snd_soc_dapm_new_controls - create new dapm controls
L
Liam Girdwood 已提交
3185
 * @dapm: DAPM context
3186 3187 3188 3189 3190 3191 3192
 * @widget: widget array
 * @num: number of widgets
 *
 * Creates new DAPM controls based upon the templates.
 *
 * Returns 0 for success else error.
 */
L
Liam Girdwood 已提交
3193
int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
3194 3195 3196
	const struct snd_soc_dapm_widget *widget,
	int num)
{
3197 3198
	struct snd_soc_dapm_widget *w;
	int i;
3199
	int ret = 0;
3200

3201
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
3202
	for (i = 0; i < num; i++) {
3203 3204
		w = snd_soc_dapm_new_control(dapm, widget);
		if (!w) {
3205
			dev_err(dapm->dev,
3206 3207
				"ASoC: Failed to create DAPM control %s\n",
				widget->name);
3208 3209
			ret = -ENOMEM;
			break;
3210
		}
3211 3212
		widget++;
	}
3213
	mutex_unlock(&dapm->card->dapm_mutex);
3214
	return ret;
3215 3216 3217
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);

3218 3219 3220 3221 3222 3223 3224
static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
				  struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_dapm_path *source_p, *sink_p;
	struct snd_soc_dai *source, *sink;
	const struct snd_soc_pcm_stream *config = w->params;
	struct snd_pcm_substream substream;
3225
	struct snd_pcm_hw_params *params = NULL;
3226 3227 3228
	u64 fmt;
	int ret;

3229 3230 3231
	if (WARN_ON(!config) ||
	    WARN_ON(list_empty(&w->sources) || list_empty(&w->sinks)))
		return -EINVAL;
3232 3233 3234 3235 3236 3237 3238

	/* We only support a single source and sink, pick the first */
	source_p = list_first_entry(&w->sources, struct snd_soc_dapm_path,
				    list_sink);
	sink_p = list_first_entry(&w->sinks, struct snd_soc_dapm_path,
				  list_source);

3239 3240 3241 3242
	if (WARN_ON(!source_p || !sink_p) ||
	    WARN_ON(!sink_p->source || !source_p->sink) ||
	    WARN_ON(!source_p->source || !sink_p->sink))
		return -EINVAL;
3243 3244 3245 3246 3247 3248 3249 3250

	source = source_p->source->priv;
	sink = sink_p->sink->priv;

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

	/* Currently very limited parameter selection */
3257 3258 3259 3260 3261 3262
	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);
3263

3264
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min =
3265
		config->rate_min;
3266
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max =
3267 3268
		config->rate_max;

3269
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min
3270
		= config->channels_min;
3271
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max
3272 3273 3274 3275 3276 3277 3278 3279 3280
		= config->channels_max;

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

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		if (source->driver->ops && source->driver->ops->hw_params) {
			substream.stream = SNDRV_PCM_STREAM_CAPTURE;
			ret = source->driver->ops->hw_params(&substream,
3281
							     params, source);
3282 3283
			if (ret != 0) {
				dev_err(source->dev,
3284
					"ASoC: hw_params() failed: %d\n", ret);
3285
				goto out;
3286 3287 3288 3289 3290
			}
		}

		if (sink->driver->ops && sink->driver->ops->hw_params) {
			substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
3291
			ret = sink->driver->ops->hw_params(&substream, params,
3292 3293 3294
							   sink);
			if (ret != 0) {
				dev_err(sink->dev,
3295
					"ASoC: hw_params() failed: %d\n", ret);
3296
				goto out;
3297 3298 3299 3300 3301
			}
		}
		break;

	case SND_SOC_DAPM_POST_PMU:
3302 3303
		ret = snd_soc_dai_digital_mute(sink, 0,
					       SNDRV_PCM_STREAM_PLAYBACK);
3304
		if (ret != 0 && ret != -ENOTSUPP)
3305
			dev_warn(sink->dev, "ASoC: Failed to unmute: %d\n", ret);
3306
		ret = 0;
3307 3308 3309
		break;

	case SND_SOC_DAPM_PRE_PMD:
3310 3311
		ret = snd_soc_dai_digital_mute(sink, 1,
					       SNDRV_PCM_STREAM_PLAYBACK);
3312
		if (ret != 0 && ret != -ENOTSUPP)
3313
			dev_warn(sink->dev, "ASoC: Failed to mute: %d\n", ret);
3314
		ret = 0;
3315 3316 3317
		break;

	default:
T
Takashi Iwai 已提交
3318
		WARN(1, "Unknown event %d\n", event);
3319 3320 3321
		return -EINVAL;
	}

3322 3323 3324
out:
	kfree(params);
	return ret;
3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351
}

int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
			 const struct snd_soc_pcm_stream *params,
			 struct snd_soc_dapm_widget *source,
			 struct snd_soc_dapm_widget *sink)
{
	struct snd_soc_dapm_route routes[2];
	struct snd_soc_dapm_widget template;
	struct snd_soc_dapm_widget *w;
	size_t len;
	char *link_name;

	len = strlen(source->name) + strlen(sink->name) + 2;
	link_name = devm_kzalloc(card->dev, len, GFP_KERNEL);
	if (!link_name)
		return -ENOMEM;
	snprintf(link_name, len, "%s-%s", source->name, sink->name);

	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;

3352
	dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name);
3353 3354 3355

	w = snd_soc_dapm_new_control(&card->dapm, &template);
	if (!w) {
3356
		dev_err(card->dev, "ASoC: Failed to create %s widget\n",
3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373
			link_name);
		return -ENOMEM;
	}

	w->params = params;

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

	routes[0].source = source->name;
	routes[0].sink = link_name;
	routes[1].source = link_name;
	routes[1].sink = sink->name;

	return snd_soc_dapm_add_routes(&card->dapm, routes,
				       ARRAY_SIZE(routes));
}

3374 3375
int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
				 struct snd_soc_dai *dai)
3376
{
3377
	struct snd_soc_dapm_widget template;
3378 3379
	struct snd_soc_dapm_widget *w;

3380 3381 3382 3383 3384 3385
	WARN_ON(dapm->dev != dai->dev);

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

	if (dai->driver->playback.stream_name) {
3386
		template.id = snd_soc_dapm_dai_in;
3387 3388 3389
		template.name = dai->driver->playback.stream_name;
		template.sname = dai->driver->playback.stream_name;

3390
		dev_dbg(dai->dev, "ASoC: adding %s widget\n",
3391 3392 3393 3394
			template.name);

		w = snd_soc_dapm_new_control(dapm, &template);
		if (!w) {
3395
			dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
3396
				dai->driver->playback.stream_name);
3397
			return -ENOMEM;
3398 3399 3400 3401 3402 3403 3404
		}

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

	if (dai->driver->capture.stream_name) {
3405
		template.id = snd_soc_dapm_dai_out;
3406 3407 3408
		template.name = dai->driver->capture.stream_name;
		template.sname = dai->driver->capture.stream_name;

3409
		dev_dbg(dai->dev, "ASoC: adding %s widget\n",
3410 3411 3412 3413
			template.name);

		w = snd_soc_dapm_new_control(dapm, &template);
		if (!w) {
3414
			dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
3415
				dai->driver->capture.stream_name);
3416
			return -ENOMEM;
3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432
		}

		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;
	struct snd_soc_dai *dai;

	/* For each DAI widget... */
	list_for_each_entry(dai_w, &card->widgets, list) {
3433 3434 3435 3436 3437
		switch (dai_w->id) {
		case snd_soc_dapm_dai_in:
		case snd_soc_dapm_dai_out:
			break;
		default:
3438
			continue;
3439
		}
3440 3441 3442 3443 3444 3445 3446 3447

		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;

3448 3449 3450
			switch (w->id) {
			case snd_soc_dapm_dai_in:
			case snd_soc_dapm_dai_out:
3451
				continue;
3452 3453 3454
			default:
				break;
			}
3455

R
Russell King 已提交
3456
			if (!w->sname || !strstr(w->sname, dai_w->name))
3457 3458 3459 3460 3461 3462
				continue;

			if (dai->driver->playback.stream_name &&
			    strstr(w->sname,
				   dai->driver->playback.stream_name)) {
				dev_dbg(dai->dev, "%s -> %s\n",
3463
					 dai->playback_widget->name, w->name);
3464

3465 3466
				snd_soc_dapm_add_path(w->dapm,
					dai->playback_widget, w, NULL, NULL);
3467 3468 3469 3470 3471 3472
			}

			if (dai->driver->capture.stream_name &&
			    strstr(w->sname,
				   dai->driver->capture.stream_name)) {
				dev_dbg(dai->dev, "%s -> %s\n",
3473
					w->name, dai->capture_widget->name);
3474

3475 3476
				snd_soc_dapm_add_path(w->dapm, w,
					dai->capture_widget, NULL, NULL);
3477 3478 3479 3480
			}
		}
	}

3481 3482
	return 0;
}
3483

3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
{
	struct snd_soc_pcm_runtime *rtd = card->rtd;
	struct snd_soc_dai *cpu_dai, *codec_dai;
	struct snd_soc_dapm_route r;
	int i;

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

	/* for each BE DAI link... */
	for (i = 0; i < card->num_rtd; i++) {
		rtd = &card->rtd[i];
		cpu_dai = rtd->cpu_dai;
		codec_dai = rtd->codec_dai;

		/* dynamic FE links have no fixed DAI mapping */
		if (rtd->dai_link->dynamic)
			continue;

		/* there is no point in connecting BE DAI links with dummies */
		if (snd_soc_dai_is_dummy(codec_dai) ||
			snd_soc_dai_is_dummy(cpu_dai))
			continue;

		/* connect BE DAI playback if widgets are valid */
		if (codec_dai->playback_widget && cpu_dai->playback_widget) {
			r.source = cpu_dai->playback_widget->name;
			r.sink = codec_dai->playback_widget->name;
			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
				cpu_dai->codec->name, r.source,
				codec_dai->platform->name, r.sink);

3516
			snd_soc_dapm_add_route(&card->dapm, &r, true);
3517 3518 3519 3520 3521 3522 3523 3524 3525 3526
		}

		/* connect BE DAI capture if widgets are valid */
		if (codec_dai->capture_widget && cpu_dai->capture_widget) {
			r.source = codec_dai->capture_widget->name;
			r.sink = cpu_dai->capture_widget->name;
			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
				codec_dai->codec->name, r.source,
				cpu_dai->platform->name, r.sink);

3527
			snd_soc_dapm_add_route(&card->dapm, &r, true);
3528 3529 3530 3531 3532
		}

	}
}

3533 3534
static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
	int event)
3535
{
3536

3537 3538 3539
	struct snd_soc_dapm_widget *w_cpu, *w_codec;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
3540

3541 3542 3543 3544 3545 3546 3547
	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
		w_cpu = cpu_dai->playback_widget;
		w_codec = codec_dai->playback_widget;
	} else {
		w_cpu = cpu_dai->capture_widget;
		w_codec = codec_dai->capture_widget;
	}
3548

3549
	if (w_cpu) {
3550

3551 3552 3553 3554 3555 3556 3557 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 3583 3584
		dapm_mark_dirty(w_cpu, "stream event");

		switch (event) {
		case SND_SOC_DAPM_STREAM_START:
			w_cpu->active = 1;
			break;
		case SND_SOC_DAPM_STREAM_STOP:
			w_cpu->active = 0;
			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;
		}
	}

	if (w_codec) {

		dapm_mark_dirty(w_codec, "stream event");

		switch (event) {
		case SND_SOC_DAPM_STREAM_START:
			w_codec->active = 1;
			break;
		case SND_SOC_DAPM_STREAM_STOP:
			w_codec->active = 0;
			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;
		}
3585 3586
	}

3587
	dapm_power_widgets(rtd->card, event);
L
Liam Girdwood 已提交
3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600
}

/**
 * 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.
 */
3601 3602
void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
			      int event)
L
Liam Girdwood 已提交
3603
{
3604
	struct snd_soc_card *card = rtd->card;
L
Liam Girdwood 已提交
3605

3606
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3607
	soc_dapm_stream_event(rtd, stream, event);
3608
	mutex_unlock(&card->dapm_mutex);
3609 3610
}

3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630
/**
 * 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);

3631
/**
3632
 * snd_soc_dapm_enable_pin - enable pin.
L
Liam Girdwood 已提交
3633
 * @dapm: DAPM context
3634
 * @pin: pin name
3635
 *
M
Mark Brown 已提交
3636
 * Enables input/output pin and its parents or children widgets iff there is
3637
 * a valid audio route and active audio stream.
3638
 *
3639 3640
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
3641
 */
L
Liam Girdwood 已提交
3642
int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
3643
{
3644 3645 3646 3647 3648 3649 3650 3651 3652
	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;
3653 3654
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
3655

3656
/**
3657
 * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
L
Liam Girdwood 已提交
3658
 * @dapm: DAPM context
3659 3660 3661 3662 3663 3664
 * @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.
 *
3665 3666
 * Requires external locking.
 *
3667 3668 3669
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
3670 3671
int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
					 const char *pin)
3672
{
3673
	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
3674

3675
	if (!w) {
3676
		dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
3677
		return -EINVAL;
3678 3679
	}

3680
	dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin);
3681 3682
	w->connected = 1;
	w->force = 1;
3683
	dapm_mark_dirty(w, "force enable");
3684

3685
	return 0;
3686
}
3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713
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;
}
3714 3715
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);

3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734
/**
 * 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);

3735 3736
/**
 * snd_soc_dapm_disable_pin - disable pin.
L
Liam Girdwood 已提交
3737
 * @dapm: DAPM context
3738 3739
 * @pin: pin name
 *
M
Mark Brown 已提交
3740
 * Disables input/output pin and its parents or children widgets.
3741
 *
3742 3743 3744
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
L
Liam Girdwood 已提交
3745 3746
int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
			     const char *pin)
3747
{
3748 3749 3750 3751 3752 3753 3754 3755 3756
	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;
3757
}
3758
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
3759

3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782
/**
 * 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);

3783 3784
/**
 * snd_soc_dapm_nc_pin - permanently disable pin.
L
Liam Girdwood 已提交
3785
 * @dapm: DAPM context
3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796
 * @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 已提交
3797
int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
3798
{
3799 3800 3801 3802 3803 3804 3805 3806 3807
	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;
3808 3809 3810
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);

3811
/**
3812
 * snd_soc_dapm_get_pin_status - get audio pin status
L
Liam Girdwood 已提交
3813
 * @dapm: DAPM context
3814
 * @pin: audio signal pin endpoint (or start point)
3815
 *
3816
 * Get audio pin status - connected or disconnected.
3817
 *
3818
 * Returns 1 for connected otherwise 0.
3819
 */
L
Liam Girdwood 已提交
3820 3821
int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
				const char *pin)
3822
{
3823
	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
3824

3825 3826
	if (w)
		return w->connected;
3827

3828 3829
	return 0;
}
3830
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
3831

3832 3833
/**
 * snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint
L
Liam Girdwood 已提交
3834
 * @dapm: DAPM context
3835 3836 3837 3838 3839 3840 3841 3842
 * @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 已提交
3843 3844
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
				const char *pin)
3845
{
3846
	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, false);
3847

3848
	if (!w) {
3849
		dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
3850
		return -EINVAL;
3851 3852
	}

3853 3854 3855
	w->ignore_suspend = 1;

	return 0;
3856 3857 3858
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);

3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907
static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card,
					      struct snd_soc_dapm_widget *w)
{
	struct snd_soc_dapm_path *p;

	list_for_each_entry(p, &card->paths, list) {
		if ((p->source == w) || (p->sink == w)) {
			dev_dbg(card->dev,
			    "... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n",
			    p->source->name, p->source->id, p->source->dapm,
			    p->sink->name, p->sink->id, p->sink->dapm);

			/* Connected to something other than the codec */
			if (p->source->dapm != p->sink->dapm)
				return true;
			/*
			 * Loopback connection from codec external pin to
			 * codec external pin
			 */
			if (p->sink->id == snd_soc_dapm_input) {
				switch (p->source->id) {
				case snd_soc_dapm_output:
				case snd_soc_dapm_micbias:
					return true;
				default:
					break;
				}
			}
		}
	}

	return false;
}

/**
 * snd_soc_dapm_auto_nc_codec_pins - call snd_soc_dapm_nc_pin for unused pins
 * @codec: The codec whose pins should be processed
 *
 * Automatically call snd_soc_dapm_nc_pin() for any external pins in the codec
 * which are unused. Pins are used if they are connected externally to the
 * codec, whether that be to some other device, or a loop-back connection to
 * the codec itself.
 */
void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
{
	struct snd_soc_card *card = codec->card;
	struct snd_soc_dapm_context *dapm = &codec->dapm;
	struct snd_soc_dapm_widget *w;

3908
	dev_dbg(codec->dev, "ASoC: Auto NC: DAPMs: card:%p codec:%p\n",
3909 3910 3911 3912 3913 3914 3915 3916 3917
		&card->dapm, &codec->dapm);

	list_for_each_entry(w, &card->widgets, list) {
		if (w->dapm != dapm)
			continue;
		switch (w->id) {
		case snd_soc_dapm_input:
		case snd_soc_dapm_output:
		case snd_soc_dapm_micbias:
3918
			dev_dbg(codec->dev, "ASoC: Auto NC: Checking widget %s\n",
3919 3920
				w->name);
			if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
3921
				dev_dbg(codec->dev,
3922 3923 3924 3925 3926 3927 3928 3929 3930 3931
					"... Not in map; disabling\n");
				snd_soc_dapm_nc_pin(dapm, w->name);
			}
			break;
		default:
			break;
		}
	}
}

3932 3933
/**
 * snd_soc_dapm_free - free dapm resources
3934
 * @dapm: DAPM context
3935 3936 3937
 *
 * Free all dapm widgets and resources.
 */
L
Liam Girdwood 已提交
3938
void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm)
3939
{
L
Liam Girdwood 已提交
3940
	snd_soc_dapm_sys_remove(dapm->dev);
3941
	dapm_debugfs_cleanup(dapm);
L
Liam Girdwood 已提交
3942
	dapm_free_widgets(dapm);
3943
	list_del(&dapm->list);
3944 3945 3946
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_free);

L
Liam Girdwood 已提交
3947
static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
M
Mark Brown 已提交
3948
{
3949
	struct snd_soc_card *card = dapm->card;
M
Mark Brown 已提交
3950 3951 3952 3953
	struct snd_soc_dapm_widget *w;
	LIST_HEAD(down_list);
	int powerdown = 0;

3954 3955
	mutex_lock(&card->dapm_mutex);

3956 3957 3958
	list_for_each_entry(w, &dapm->card->widgets, list) {
		if (w->dapm != dapm)
			continue;
M
Mark Brown 已提交
3959
		if (w->power) {
3960
			dapm_seq_insert(w, &down_list, false);
3961
			w->power = 0;
M
Mark Brown 已提交
3962 3963 3964 3965 3966 3967 3968 3969
			powerdown = 1;
		}
	}

	/* If there were no widgets to power down we're already in
	 * standby.
	 */
	if (powerdown) {
3970 3971 3972
		if (dapm->bias_level == SND_SOC_BIAS_ON)
			snd_soc_dapm_set_bias_level(dapm,
						    SND_SOC_BIAS_PREPARE);
3973
		dapm_seq_run(card, &down_list, 0, false);
3974 3975 3976
		if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
			snd_soc_dapm_set_bias_level(dapm,
						    SND_SOC_BIAS_STANDBY);
M
Mark Brown 已提交
3977
	}
3978 3979

	mutex_unlock(&card->dapm_mutex);
3980 3981 3982 3983 3984 3985 3986 3987 3988
}

/*
 * snd_soc_dapm_shutdown - callback for system shutdown
 */
void snd_soc_dapm_shutdown(struct snd_soc_card *card)
{
	struct snd_soc_codec *codec;

3989
	list_for_each_entry(codec, &card->codec_dev_list, card_list) {
L
Liam Girdwood 已提交
3990
		soc_dapm_shutdown_codec(&codec->dapm);
3991 3992 3993
		if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
			snd_soc_dapm_set_bias_level(&codec->dapm,
						    SND_SOC_BIAS_OFF);
L
Liam Girdwood 已提交
3994
	}
M
Mark Brown 已提交
3995 3996
}

3997
/* Module information */
3998
MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
3999 4000
MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
MODULE_LICENSE("GPL");