soc-dapm.c 93.0 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 115 116 117 118 119
static void dapm_assert_locked(struct snd_soc_dapm_context *dapm)
{
	if (dapm->card && dapm->card->instantiated)
		lockdep_assert_held(&dapm->card->dapm_mutex);
}

120
static void pop_wait(u32 pop_time)
121 122 123 124 125
{
	if (pop_time)
		schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
}

126
static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
127 128
{
	va_list args;
129
	char *buf;
130

131 132
	if (!pop_time)
		return;
133

134 135 136
	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (buf == NULL)
		return;
137

138 139
	va_start(args, fmt);
	vsnprintf(buf, PAGE_SIZE, fmt, args);
140
	dev_info(dev, "%s", buf);
141
	va_end(args);
142 143

	kfree(buf);
144 145
}

146 147 148 149 150
static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)
{
	return !list_empty(&w->dirty);
}

151
static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
152
{
153 154
	dapm_assert_locked(w->dapm);

155 156 157
	if (!dapm_dirty_widget(w)) {
		dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",
			 w->name, reason);
158
		list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);
159
	}
160 161
}

162
void dapm_mark_endpoints_dirty(struct snd_soc_card *card)
163 164 165 166 167 168
{
	struct snd_soc_dapm_widget *w;

	mutex_lock(&card->dapm_mutex);

	list_for_each_entry(w, &card->widgets, list) {
169 170
		if (w->is_sink || w->is_source)
			dapm_mark_dirty(w, "Rechecking endpoints");
171 172 173 174
	}

	mutex_unlock(&card->dapm_mutex);
}
175
EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty);
176

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->wlist);
251 252 253 254 255 256 257 258
	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);

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

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

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

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

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

	return 0;
}

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

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

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)

322
unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)
323 324 325 326 327
{
	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);

	return data->value;
}
328
EXPORT_SYMBOL_GPL(dapm_kcontrol_get_value);
329 330 331 332 333 334 335 336 337

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 352 353 354 355 356 357 358 359 360
/**
 * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a
 *  kcontrol
 * @kcontrol: The kcontrol
 *
 * Note: This function must only be used on kcontrols that are known to have
 * been registered for a CODEC. Otherwise the behaviour is undefined.
 */
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
	struct snd_kcontrol *kcontrol)
{
	return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm);

361 362 363 364 365 366
/**
 * 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)
{
367
	return snd_soc_dapm_to_codec(snd_soc_dapm_kcontrol_dapm(kcontrol));
368 369 370
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec);

371 372 373 374
static void dapm_reset(struct snd_soc_card *card)
{
	struct snd_soc_dapm_widget *w;

375 376
	lockdep_assert_held(&card->dapm_mutex);

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

	list_for_each_entry(w, &card->widgets, list) {
380
		w->new_power = w->power;
381 382 383 384 385 386
		w->power_checked = false;
		w->inputs = -1;
		w->outputs = -1;
	}
}

387 388 389 390 391 392 393
static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm)
{
	if (!dapm->component)
		return NULL;
	return dapm->component->name_prefix;
}

394
static int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg,
395
	unsigned int *value)
396
{
397
	if (!dapm->component)
398
		return -EIO;
399
	return snd_soc_component_read(dapm->component, reg, value);
400 401
}

402
static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm,
403
	int reg, unsigned int mask, unsigned int value)
404
{
405
	if (!dapm->component)
406
		return -EIO;
407
	return snd_soc_component_update_bits_async(dapm->component, reg,
408
		mask, value);
409 410
}

411 412 413 414 415 416 417 418
static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm,
	int reg, unsigned int mask, unsigned int value)
{
	if (!dapm->component)
		return -EIO;
	return snd_soc_component_test_bits(dapm->component, reg, mask, value);
}

419 420
static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
{
421 422
	if (dapm->component)
		snd_soc_component_async_complete(dapm->component);
423 424
}

425 426
/**
 * snd_soc_dapm_set_bias_level - set the bias level for the system
427
 * @dapm: DAPM context
428 429 430 431 432 433
 * @level: level to configure
 *
 * Configure the bias (power) levels for the SoC audio device.
 *
 * Returns 0 for success else error.
 */
434
static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
L
Liam Girdwood 已提交
435
				       enum snd_soc_bias_level level)
436
{
437
	struct snd_soc_card *card = dapm->card;
438 439
	int ret = 0;

M
Mark Brown 已提交
440 441
	trace_snd_soc_bias_level_start(card, level);

442
	if (card && card->set_bias_level)
443
		ret = card->set_bias_level(card, dapm, level);
444 445 446
	if (ret != 0)
		goto out;

447 448 449
	if (dapm->set_bias_level)
		ret = dapm->set_bias_level(dapm, level);
	else if (!card || dapm != &card->dapm)
450 451
		dapm->bias_level = level;

452 453 454 455
	if (ret != 0)
		goto out;

	if (card && card->set_bias_level_post)
456
		ret = card->set_bias_level_post(card, dapm, level);
457
out:
M
Mark Brown 已提交
458 459
	trace_snd_soc_bias_level_done(card, level);

460 461 462
	return ret;
}

M
Mark Brown 已提交
463
/* connect mux widget to its interconnecting audio paths */
L
Liam Girdwood 已提交
464
static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
465
	struct snd_soc_dapm_path *path, const char *control_name)
466
{
467
	const struct snd_kcontrol_new *kcontrol = &path->sink->kcontrol_news[0];
468
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
469
	unsigned int val, item;
470
	int i;
471

472
	if (e->reg != SND_SOC_NOPM) {
473
		soc_dapm_read(dapm, e->reg, &val);
474 475 476
		val = (val >> e->shift_l) & e->mask;
		item = snd_soc_enum_val_to_item(e, val);
	} else {
477 478 479 480 481 482
		/* 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.
		 */
483
		item = 0;
484
	}
P
Peter Ujfalusi 已提交
485

486
	for (i = 0; i < e->items; i++) {
487
		if (!(strcmp(control_name, e->texts[i]))) {
488
			path->name = e->texts[i];
489 490 491 492
			if (i == item)
				path->connect = 1;
			else
				path->connect = 0;
493 494 495 496 497 498 499
			return 0;
		}
	}

	return -ENODEV;
}

500
/* set up initial codec paths */
501
static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i)
502 503
{
	struct soc_mixer_control *mc = (struct soc_mixer_control *)
504
		p->sink->kcontrol_news[i].private_value;
505 506 507 508 509 510 511 512
	unsigned int reg = mc->reg;
	unsigned int shift = mc->shift;
	unsigned int max = mc->max;
	unsigned int mask = (1 << fls(max)) - 1;
	unsigned int invert = mc->invert;
	unsigned int val;

	if (reg != SND_SOC_NOPM) {
513
		soc_dapm_read(p->sink->dapm, reg, &val);
514 515 516 517 518 519 520 521 522
		val = (val >> shift) & mask;
		if (invert)
			val = max - val;
		p->connect = !!val;
	} else {
		p->connect = 0;
	}
}

M
Mark Brown 已提交
523
/* connect mixer widget to its interconnecting audio paths */
L
Liam Girdwood 已提交
524
static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,
525 526 527 528 529
	struct snd_soc_dapm_path *path, const char *control_name)
{
	int i;

	/* search for mixer kcontrol */
530 531 532 533
	for (i = 0; i < path->sink->num_kcontrols; i++) {
		if (!strcmp(control_name, path->sink->kcontrol_news[i].name)) {
			path->name = path->sink->kcontrol_news[i].name;
			dapm_set_mixer_path_status(path, i);
534 535 536 537 538 539
			return 0;
		}
	}
	return -ENODEV;
}

540
static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
541
	struct snd_soc_dapm_widget *kcontrolw,
542 543 544 545 546 547 548 549 550
	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) {
551 552
		if (w == kcontrolw || w->dapm != kcontrolw->dapm)
			continue;
553 554 555 556 557 558 559 560 561 562 563 564
		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;
}

565 566 567 568 569
/*
 * 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,
570
	int kci)
571
{
572
	struct snd_soc_dapm_context *dapm = w->dapm;
573
	struct snd_card *card = dapm->card->snd_card;
574
	const char *prefix;
575 576 577 578
	size_t prefix_len;
	int shared;
	struct snd_kcontrol *kcontrol;
	bool wname_in_long_name, kcname_in_long_name;
D
Daniel Mack 已提交
579
	char *long_name = NULL;
580
	const char *name;
D
Daniel Mack 已提交
581
	int ret = 0;
582

583
	prefix = soc_dapm_prefix(dapm);
584 585 586 587 588
	if (prefix)
		prefix_len = strlen(prefix) + 1;
	else
		prefix_len = 0;

589 590
	shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],
					 &kcontrol);
591

592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
	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;
613
			}
614 615 616 617 618 619 620 621
		}

		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.
622
			 */
623
			long_name = kasprintf(GFP_KERNEL, "%s %s",
624 625
				 w->name + prefix_len,
				 w->kcontrol_news[kci].name);
626
			if (long_name == NULL)
627
				return -ENOMEM;
628 629 630 631 632 633 634 635 636

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

638
		kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name,
639
					prefix);
D
Daniel Mack 已提交
640 641 642 643 644
		if (!kcontrol) {
			ret = -ENOMEM;
			goto exit_free;
		}

645
		kcontrol->private_free = dapm_kcontrol_free;
646 647 648 649

		ret = dapm_kcontrol_data_alloc(w, kcontrol);
		if (ret) {
			snd_ctl_free_one(kcontrol);
D
Daniel Mack 已提交
650
			goto exit_free;
651 652
		}

653 654 655 656 657
		ret = snd_ctl_add(card, kcontrol);
		if (ret < 0) {
			dev_err(dapm->dev,
				"ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
				w->name, name, ret);
D
Daniel Mack 已提交
658
			goto exit_free;
659 660
		}
	}
661

662
	ret = dapm_kcontrol_add_widget(kcontrol, w);
D
Daniel Mack 已提交
663 664
	if (ret == 0)
		w->kcontrols[kci] = kcontrol;
665

D
Daniel Mack 已提交
666 667
exit_free:
	kfree(long_name);
668

D
Daniel Mack 已提交
669
	return ret;
670
}
671

672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
/* 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]) {
687
				dapm_kcontrol_add_path(w->kcontrols[i], path);
688
				continue;
689
			}
690

691
			ret = dapm_create_or_share_mixmux_kcontrol(w, i);
692 693
			if (ret < 0)
				return ret;
694 695

			dapm_kcontrol_add_path(w->kcontrols[i], path);
696 697
		}
	}
698 699

	return 0;
700 701 702
}

/* create new dapm mux control */
703
static int dapm_new_mux(struct snd_soc_dapm_widget *w)
704
{
705
	struct snd_soc_dapm_context *dapm = w->dapm;
706
	struct snd_soc_dapm_path *path;
707
	int ret;
708

709 710
	if (w->num_kcontrols != 1) {
		dev_err(dapm->dev,
711
			"ASoC: mux %s has incorrect number of controls\n",
712
			w->name);
713 714 715
		return -EINVAL;
	}

716
	if (list_empty(&w->sources)) {
717 718
		dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name);
		return -EINVAL;
719
	}
L
Liam Girdwood 已提交
720

721
	ret = dapm_create_or_share_mixmux_kcontrol(w, 0);
722 723
	if (ret < 0)
		return ret;
724

725 726 727 728
	list_for_each_entry(path, &w->sources, list_sink) {
		if (path->name)
			dapm_kcontrol_add_path(w->kcontrols[0], path);
	}
729

730
	return 0;
731 732 733
}

/* create new dapm volume control */
734
static int dapm_new_pga(struct snd_soc_dapm_widget *w)
735
{
736
	if (w->num_kcontrols)
737
		dev_err(w->dapm->dev,
738
			"ASoC: PGA controls not supported: '%s'\n", w->name);
739

740
	return 0;
741 742
}

743 744 745 746 747 748
/* 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)
{
749
	int level = snd_power_get_state(widget->dapm->card->snd_card);
750

751
	switch (level) {
752 753
	case SNDRV_CTL_POWER_D3hot:
	case SNDRV_CTL_POWER_D3cold:
754
		if (widget->ignore_suspend)
755
			dev_dbg(widget->dapm->dev, "ASoC: %s ignoring suspend\n",
756
				widget->name);
757
		return widget->ignore_suspend;
758 759 760 761 762
	default:
		return 1;
	}
}

763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
/* 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) {
787
		dev_err(w->dapm->dev, "ASoC: can't allocate widget list for %s\n",
788 789 790 791 792 793
			w->name);
		return -ENOMEM;
	}
	wlist = *list;

	/* insert the widget */
794
	dev_dbg(w->dapm->dev, "ASoC: added %s in widget list pos %d\n",
795 796 797 798 799 800 801
			w->name, wlist->num_widgets);

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

802 803 804 805
/*
 * Recursively check for a completed path to an active or physically connected
 * output widget. Returns number of complete paths.
 */
806 807
static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
	struct snd_soc_dapm_widget_list **list)
808 809 810 811
{
	struct snd_soc_dapm_path *path;
	int con = 0;

812 813 814
	if (widget->outputs >= 0)
		return widget->outputs;

815 816
	DAPM_UPDATE_STAT(widget, path_checks);

817 818 819
	if (widget->is_sink && widget->connected) {
		widget->outputs = snd_soc_dapm_suspend_check(widget);
		return widget->outputs;
820 821 822
	}

	list_for_each_entry(path, &widget->sinks, list_source) {
823 824
		DAPM_UPDATE_STAT(widget, neighbour_checks);

825
		if (path->weak || path->is_supply)
826 827
			continue;

M
Mark Brown 已提交
828 829 830
		if (path->walking)
			return 1;

831 832
		trace_snd_soc_dapm_output_path(widget, path);

833
		if (path->connect) {
M
Mark Brown 已提交
834
			path->walking = 1;
835 836 837 838 839 840

			/* 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) {
841 842
					dev_err(widget->dapm->dev,
						"ASoC: could not add widget %s\n",
843
						widget->name);
M
Mark Brown 已提交
844
					path->walking = 0;
845 846 847 848 849
					return con;
				}
			}

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

			path->walking = 0;
852 853 854
		}
	}

855 856
	widget->outputs = con;

857 858 859 860 861 862 863
	return con;
}

/*
 * Recursively check for a completed path to an active or physically connected
 * input widget. Returns number of complete paths.
 */
864 865
static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
	struct snd_soc_dapm_widget_list **list)
866 867 868 869
{
	struct snd_soc_dapm_path *path;
	int con = 0;

870 871 872
	if (widget->inputs >= 0)
		return widget->inputs;

873 874
	DAPM_UPDATE_STAT(widget, path_checks);

875 876 877
	if (widget->is_source && widget->connected) {
		widget->inputs = snd_soc_dapm_suspend_check(widget);
		return widget->inputs;
878 879 880
	}

	list_for_each_entry(path, &widget->sources, list_sink) {
881 882
		DAPM_UPDATE_STAT(widget, neighbour_checks);

883
		if (path->weak || path->is_supply)
884 885
			continue;

M
Mark Brown 已提交
886 887 888
		if (path->walking)
			return 1;

889 890
		trace_snd_soc_dapm_input_path(widget, path);

891
		if (path->connect) {
M
Mark Brown 已提交
892
			path->walking = 1;
893 894 895 896

			/* do we need to add this widget to the list ? */
			if (list) {
				int err;
897
				err = dapm_list_add_widget(list, path->source);
898
				if (err < 0) {
899 900
					dev_err(widget->dapm->dev,
						"ASoC: could not add widget %s\n",
901
						widget->name);
M
Mark Brown 已提交
902
					path->walking = 0;
903 904 905 906 907
					return con;
				}
			}

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

			path->walking = 0;
910 911 912
		}
	}

913 914
	widget->inputs = con;

915 916 917
	return con;
}

918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938
/**
 * 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);

939
	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
940
		paths = is_connected_output_ep(dai->playback_widget, list);
941
	else
942
		paths = is_connected_input_ep(dai->capture_widget, list);
943 944 945 946 947 948 949

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

	return paths;
}

950 951 952 953 954 955
/*
 * Handler for regulator supply widget.
 */
int dapm_regulator_event(struct snd_soc_dapm_widget *w,
		   struct snd_kcontrol *kcontrol, int event)
{
956 957
	int ret;

958 959
	soc_dapm_async_complete(w->dapm);

960
	if (SND_SOC_DAPM_EVENT_ON(event)) {
961
		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
962
			ret = regulator_allow_bypass(w->regulator, false);
963 964
			if (ret != 0)
				dev_warn(w->dapm->dev,
965
					 "ASoC: Failed to unbypass %s: %d\n",
966 967 968
					 w->name, ret);
		}

969
		return regulator_enable(w->regulator);
970
	} else {
971
		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
972
			ret = regulator_allow_bypass(w->regulator, true);
973 974
			if (ret != 0)
				dev_warn(w->dapm->dev,
975
					 "ASoC: Failed to bypass %s: %d\n",
976 977 978
					 w->name, ret);
		}

979
		return regulator_disable_deferred(w->regulator, w->shift);
980
	}
981 982 983
}
EXPORT_SYMBOL_GPL(dapm_regulator_event);

984 985 986 987 988 989 990 991 992
/*
 * 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;

993 994
	soc_dapm_async_complete(w->dapm);

995
#ifdef CONFIG_HAVE_CLK
996
	if (SND_SOC_DAPM_EVENT_ON(event)) {
997
		return clk_prepare_enable(w->clk);
998
	} else {
999
		clk_disable_unprepare(w->clk);
1000 1001
		return 0;
	}
1002
#endif
1003
	return 0;
1004 1005 1006
}
EXPORT_SYMBOL_GPL(dapm_clock_event);

1007 1008
static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
{
1009 1010 1011
	if (w->power_checked)
		return w->new_power;

1012
	if (w->force)
1013
		w->new_power = 1;
1014
	else
1015 1016 1017 1018 1019
		w->new_power = w->power_check(w);

	w->power_checked = true;

	return w->new_power;
1020 1021
}

1022 1023 1024 1025 1026 1027
/* 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;

1028 1029
	DAPM_UPDATE_STAT(w, power_checks);

1030 1031
	in = is_connected_input_ep(w, NULL);
	out = is_connected_output_ep(w, NULL);
1032 1033 1034
	return out != 0 && in != 0;
}

1035 1036 1037 1038 1039
/* 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;

1040 1041
	DAPM_UPDATE_STAT(w, power_checks);

1042 1043
	/* Check if one of our outputs is connected */
	list_for_each_entry(path, &w->sinks, list_source) {
1044 1045
		DAPM_UPDATE_STAT(w, neighbour_checks);

1046 1047 1048
		if (path->weak)
			continue;

1049 1050 1051 1052
		if (path->connected &&
		    !path->connected(path->source, path->sink))
			continue;

1053 1054
		if (dapm_widget_power_check(path->sink))
			return 1;
1055 1056
	}

1057
	return 0;
1058 1059
}

1060 1061 1062 1063 1064
static int dapm_always_on_check_power(struct snd_soc_dapm_widget *w)
{
	return 1;
}

1065 1066
static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
			    struct snd_soc_dapm_widget *b,
1067
			    bool power_up)
1068
{
1069 1070 1071 1072 1073 1074 1075
	int *sort;

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

1076 1077
	if (sort[a->id] != sort[b->id])
		return sort[a->id] - sort[b->id];
1078 1079 1080 1081 1082 1083
	if (a->subseq != b->subseq) {
		if (power_up)
			return a->subseq - b->subseq;
		else
			return b->subseq - a->subseq;
	}
1084 1085
	if (a->reg != b->reg)
		return a->reg - b->reg;
1086 1087
	if (a->dapm != b->dapm)
		return (unsigned long)a->dapm - (unsigned long)b->dapm;
1088

1089 1090
	return 0;
}
1091

1092 1093 1094
/* 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,
1095
			    bool power_up)
1096 1097 1098 1099
{
	struct snd_soc_dapm_widget *w;

	list_for_each_entry(w, list, power_list)
1100
		if (dapm_seq_compare(new_widget, w, power_up) < 0) {
1101 1102 1103 1104 1105 1106 1107
			list_add_tail(&new_widget->power_list, &w->power_list);
			return;
		}

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

1108
static void dapm_seq_check_event(struct snd_soc_card *card,
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
				 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;
1131 1132 1133 1134 1135 1136 1137 1138
	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;
1139
	default:
T
Takashi Iwai 已提交
1140
		WARN(1, "Unknown event %d\n", event);
1141 1142 1143
		return;
	}

1144
	if (w->new_power != power)
1145 1146 1147
		return;

	if (w->event && (w->event_flags & event)) {
1148
		pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
1149
			w->name, ev_name);
1150
		soc_dapm_async_complete(w->dapm);
M
Mark Brown 已提交
1151
		trace_snd_soc_dapm_widget_event_start(w, event);
1152
		ret = w->event(w, NULL, event);
M
Mark Brown 已提交
1153
		trace_snd_soc_dapm_widget_event_done(w, event);
1154
		if (ret < 0)
1155
			dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n",
1156 1157 1158 1159
			       ev_name, w->name, ret);
	}
}

1160
/* Apply the coalesced changes from a DAPM sequence */
1161
static void dapm_seq_run_coalesced(struct snd_soc_card *card,
1162
				   struct list_head *pending)
1163
{
1164
	struct snd_soc_dapm_context *dapm;
1165
	struct snd_soc_dapm_widget *w;
1166
	int reg;
1167 1168 1169
	unsigned int value = 0;
	unsigned int mask = 0;

1170 1171 1172
	w = list_first_entry(pending, struct snd_soc_dapm_widget, power_list);
	reg = w->reg;
	dapm = w->dapm;
1173 1174

	list_for_each_entry(w, pending, power_list) {
1175
		WARN_ON(reg != w->reg || dapm != w->dapm);
1176
		w->power = w->new_power;
1177

1178 1179 1180
		mask |= w->mask << w->shift;
		if (w->power)
			value |= w->on_val << w->shift;
1181
		else
1182
			value |= w->off_val << w->shift;
1183

1184
		pop_dbg(dapm->dev, card->pop_time,
1185 1186
			"pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
			w->name, reg, value, mask);
1187

1188
		/* Check for events */
1189 1190
		dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMU);
		dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMD);
1191 1192 1193
	}

	if (reg >= 0) {
1194 1195 1196 1197
		/* Any widget will do, they should all be updating the
		 * same register.
		 */

1198
		pop_dbg(dapm->dev, card->pop_time,
1199
			"pop test : Applying 0x%x/0x%x to %x in %dms\n",
1200 1201
			value, mask, reg, card->pop_time);
		pop_wait(card->pop_time);
1202
		soc_dapm_update_bits(dapm, reg, mask, value);
1203 1204
	}

1205
	list_for_each_entry(w, pending, power_list) {
1206 1207
		dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMU);
		dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMD);
1208
	}
1209
}
1210

1211 1212 1213 1214 1215 1216 1217 1218
/* 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.
 */
1219 1220
static void dapm_seq_run(struct snd_soc_card *card,
	struct list_head *list, int event, bool power_up)
1221 1222
{
	struct snd_soc_dapm_widget *w, *n;
1223
	struct snd_soc_dapm_context *d;
1224 1225
	LIST_HEAD(pending);
	int cur_sort = -1;
1226
	int cur_subseq = -1;
1227
	int cur_reg = SND_SOC_NOPM;
1228
	struct snd_soc_dapm_context *cur_dapm = NULL;
1229
	int ret, i;
1230 1231 1232 1233 1234 1235
	int *sort;

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

1237 1238 1239 1240
	list_for_each_entry_safe(w, n, list, power_list) {
		ret = 0;

		/* Do we need to apply any queued changes? */
1241
		if (sort[w->id] != cur_sort || w->reg != cur_reg ||
1242
		    w->dapm != cur_dapm || w->subseq != cur_subseq) {
1243
			if (!list_empty(&pending))
1244
				dapm_seq_run_coalesced(card, &pending);
1245

1246 1247 1248 1249
			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,
1250 1251
								       i,
								       cur_subseq);
1252 1253
			}

1254 1255 1256
			if (cur_dapm && w->dapm != cur_dapm)
				soc_dapm_async_complete(cur_dapm);

1257 1258
			INIT_LIST_HEAD(&pending);
			cur_sort = -1;
1259
			cur_subseq = INT_MIN;
1260
			cur_reg = SND_SOC_NOPM;
1261
			cur_dapm = NULL;
1262 1263
		}

1264 1265 1266
		switch (w->id) {
		case snd_soc_dapm_pre:
			if (!w->event)
1267 1268
				list_for_each_entry_safe_continue(w, n, list,
								  power_list);
1269

1270
			if (event == SND_SOC_DAPM_STREAM_START)
1271 1272
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_PRE_PMU);
1273
			else if (event == SND_SOC_DAPM_STREAM_STOP)
1274 1275 1276 1277 1278 1279
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_PRE_PMD);
			break;

		case snd_soc_dapm_post:
			if (!w->event)
1280 1281
				list_for_each_entry_safe_continue(w, n, list,
								  power_list);
1282

1283
			if (event == SND_SOC_DAPM_STREAM_START)
1284 1285
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_POST_PMU);
1286
			else if (event == SND_SOC_DAPM_STREAM_STOP)
1287 1288 1289 1290
				ret = w->event(w,
					       NULL, SND_SOC_DAPM_POST_PMD);
			break;

1291
		default:
1292 1293
			/* Queue it up for application */
			cur_sort = sort[w->id];
1294
			cur_subseq = w->subseq;
1295
			cur_reg = w->reg;
1296
			cur_dapm = w->dapm;
1297 1298
			list_move(&w->power_list, &pending);
			break;
1299
		}
1300 1301

		if (ret < 0)
1302
			dev_err(w->dapm->dev,
1303
				"ASoC: Failed to apply widget power: %d\n", ret);
1304
	}
1305 1306

	if (!list_empty(&pending))
1307
		dapm_seq_run_coalesced(card, &pending);
1308 1309 1310 1311 1312

	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,
1313
						       i, cur_subseq);
1314
	}
1315 1316 1317 1318

	list_for_each_entry(d, &card->dapm_list, list) {
		soc_dapm_async_complete(d);
	}
1319 1320
}

1321
static void dapm_widget_update(struct snd_soc_card *card)
1322
{
1323
	struct snd_soc_dapm_update *update = card->update;
1324 1325 1326
	struct snd_soc_dapm_widget_list *wlist;
	struct snd_soc_dapm_widget *w = NULL;
	unsigned int wi;
1327 1328
	int ret;

1329
	if (!update || !dapm_kcontrol_is_powered(update->kcontrol))
1330 1331
		return;

1332
	wlist = dapm_kcontrol_get_wlist(update->kcontrol);
1333

1334 1335 1336 1337 1338 1339
	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)
1340
				dev_err(w->dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",
1341 1342
					   w->name, ret);
		}
1343 1344
	}

1345 1346 1347
	if (!w)
		return;

1348 1349
	ret = soc_dapm_update_bits(w->dapm, update->reg, update->mask,
		update->val);
1350
	if (ret < 0)
1351
		dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",
1352
			w->name, ret);
1353

1354 1355 1356 1357 1358 1359
	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)
1360
				dev_err(w->dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",
1361 1362
					   w->name, ret);
		}
1363 1364 1365
	}
}

1366 1367 1368 1369 1370 1371 1372 1373
/* 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;

1374 1375 1376
	/* 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) {
1377 1378 1379
		if (d->dev)
			pm_runtime_get_sync(d->dev);

1380 1381 1382
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
		if (ret != 0)
			dev_err(d->dev,
1383
				"ASoC: Failed to turn on bias: %d\n", ret);
1384 1385
	}

1386 1387 1388 1389 1390
	/* Prepare for a transition to ON or away from ON */
	if ((d->target_bias_level == SND_SOC_BIAS_ON &&
	     d->bias_level != SND_SOC_BIAS_ON) ||
	    (d->target_bias_level != SND_SOC_BIAS_ON &&
	     d->bias_level == SND_SOC_BIAS_ON)) {
1391 1392 1393
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);
		if (ret != 0)
			dev_err(d->dev,
1394
				"ASoC: Failed to prepare bias: %d\n", ret);
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
	}
}

/* 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 */
1407 1408 1409
	if (d->bias_level == SND_SOC_BIAS_PREPARE &&
	    (d->target_bias_level == SND_SOC_BIAS_STANDBY ||
	     d->target_bias_level == SND_SOC_BIAS_OFF)) {
1410 1411
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
		if (ret != 0)
1412
			dev_err(d->dev, "ASoC: Failed to apply standby bias: %d\n",
1413 1414
				ret);
	}
1415

1416
	/* If we're in standby and can support bias off then do that */
1417 1418
	if (d->bias_level == SND_SOC_BIAS_STANDBY &&
	    d->target_bias_level == SND_SOC_BIAS_OFF) {
1419 1420
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
		if (ret != 0)
1421 1422
			dev_err(d->dev, "ASoC: Failed to turn off bias: %d\n",
				ret);
1423 1424

		if (d->dev)
1425
			pm_runtime_put(d->dev);
1426 1427 1428
	}

	/* If we just powered up then move to active bias */
1429 1430
	if (d->bias_level == SND_SOC_BIAS_PREPARE &&
	    d->target_bias_level == SND_SOC_BIAS_ON) {
1431 1432
		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON);
		if (ret != 0)
1433
			dev_err(d->dev, "ASoC: Failed to apply active bias: %d\n",
1434 1435 1436
				ret);
	}
}
1437

1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449
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)
1450
		dapm_mark_dirty(peer, "peer state change");
1451 1452
}

1453 1454 1455 1456
static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
				  struct list_head *up_list,
				  struct list_head *down_list)
{
1457 1458
	struct snd_soc_dapm_path *path;

1459 1460 1461 1462 1463
	if (w->power == power)
		return;

	trace_snd_soc_dapm_widget_power(w, power);

1464
	/* If we changed our power state perhaps our neigbours changed
1465
	 * also.
1466
	 */
1467 1468 1469
	list_for_each_entry(path, &w->sources, list_sink)
		dapm_widget_set_peer_power(path->source, power, path->connect);

1470 1471
	/* Supplies can't affect their outputs, only their inputs */
	if (!w->is_supply) {
1472 1473 1474
		list_for_each_entry(path, &w->sinks, list_source)
			dapm_widget_set_peer_power(path->sink, power,
						   path->connect);
1475 1476
	}

1477 1478 1479 1480 1481 1482
	if (power)
		dapm_seq_insert(w, up_list, true);
	else
		dapm_seq_insert(w, down_list, false);
}

1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497
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:
1498
		power = dapm_widget_power_check(w);
1499

1500
		dapm_widget_set_power(w, power, up_list, down_list);
1501 1502 1503 1504
		break;
	}
}

1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520
static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm)
{
	if (dapm->idle_bias_off)
		return true;

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

	return false;
}

1521 1522 1523 1524 1525 1526 1527 1528 1529
/*
 * 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).
 */
1530
static int dapm_power_widgets(struct snd_soc_card *card, int event)
1531 1532
{
	struct snd_soc_dapm_widget *w;
1533
	struct snd_soc_dapm_context *d;
1534 1535
	LIST_HEAD(up_list);
	LIST_HEAD(down_list);
1536
	ASYNC_DOMAIN_EXCLUSIVE(async_domain);
1537
	enum snd_soc_bias_level bias;
1538

1539 1540
	lockdep_assert_held(&card->dapm_mutex);

M
Mark Brown 已提交
1541 1542
	trace_snd_soc_dapm_start(card);

1543
	list_for_each_entry(d, &card->dapm_list, list) {
1544
		if (dapm_idle_bias_off(d))
1545 1546 1547
			d->target_bias_level = SND_SOC_BIAS_OFF;
		else
			d->target_bias_level = SND_SOC_BIAS_STANDBY;
1548
	}
1549

1550
	dapm_reset(card);
1551

1552
	/* Check which widgets we need to power and store them in
1553 1554 1555 1556
	 * 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.
1557
	 */
1558
	list_for_each_entry(w, &card->dapm_dirty, dirty) {
1559
		dapm_power_one_widget(w, &up_list, &down_list);
1560 1561
	}

1562
	list_for_each_entry(w, &card->widgets, list) {
1563 1564 1565 1566 1567 1568 1569 1570 1571
		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;
		}
1572

1573
		if (w->new_power) {
1574 1575 1576 1577 1578
			d = w->dapm;

			/* Supplies and micbiases only bring the
			 * context up to STANDBY as unless something
			 * else is active and passing audio they
1579 1580 1581
			 * generally don't require full power.  Signal
			 * generators are virtual pins and have no
			 * power impact themselves.
1582 1583
			 */
			switch (w->id) {
1584
			case snd_soc_dapm_siggen:
1585
			case snd_soc_dapm_vmid:
1586
				break;
1587
			case snd_soc_dapm_supply:
1588
			case snd_soc_dapm_regulator_supply:
1589
			case snd_soc_dapm_clock_supply:
1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601
			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;
			}
		}

	}

1602 1603 1604
	/* Force all contexts in the card to the same bias state if
	 * they're not ground referenced.
	 */
1605
	bias = SND_SOC_BIAS_OFF;
1606
	list_for_each_entry(d, &card->dapm_list, list)
1607 1608
		if (d->target_bias_level > bias)
			bias = d->target_bias_level;
1609
	list_for_each_entry(d, &card->dapm_list, list)
1610
		if (!dapm_idle_bias_off(d))
1611
			d->target_bias_level = bias;
1612

1613
	trace_snd_soc_dapm_walk_done(card);
1614

1615 1616 1617 1618 1619 1620 1621 1622
	/* Run card bias changes at first */
	dapm_pre_sequence_async(&card->dapm, 0);
	/* Run other bias changes in parallel */
	list_for_each_entry(d, &card->dapm_list, list) {
		if (d != &card->dapm)
			async_schedule_domain(dapm_pre_sequence_async, d,
						&async_domain);
	}
1623
	async_synchronize_full_domain(&async_domain);
1624

1625
	list_for_each_entry(w, &down_list, power_list) {
1626
		dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMD);
1627 1628
	}

1629
	list_for_each_entry(w, &up_list, power_list) {
1630
		dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMU);
1631 1632
	}

1633
	/* Power down widgets first; try to avoid amplifying pops. */
1634
	dapm_seq_run(card, &down_list, event, false);
1635

1636
	dapm_widget_update(card);
1637

1638
	/* Now power up. */
1639
	dapm_seq_run(card, &up_list, event, true);
1640

1641
	/* Run all the bias changes in parallel */
1642 1643 1644 1645 1646
	list_for_each_entry(d, &card->dapm_list, list) {
		if (d != &card->dapm)
			async_schedule_domain(dapm_post_sequence_async, d,
						&async_domain);
	}
1647
	async_synchronize_full_domain(&async_domain);
1648 1649
	/* Run card bias changes at last */
	dapm_post_sequence_async(&card->dapm, 0);
1650

1651 1652 1653 1654 1655 1656
	/* 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);
	}

1657
	pop_dbg(card->dev, card->pop_time,
1658
		"DAPM sequencing finished, waiting %dms\n", card->pop_time);
1659
	pop_wait(card->pop_time);
1660

M
Mark Brown 已提交
1661 1662
	trace_snd_soc_dapm_done(card);

1663
	return 0;
1664 1665
}

1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680
#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;

1681 1682 1683 1684 1685 1686 1687 1688
	/* Supply widgets are not handled by is_connected_{input,output}_ep() */
	if (w->is_supply) {
		in = 0;
		out = 0;
	} else {
		in = is_connected_input_ep(w, NULL);
		out = is_connected_output_ep(w, NULL);
	}
1689

1690 1691 1692
	ret = snprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
		       w->name, w->power ? "On" : "Off",
		       w->force ? " (forced)" : "", in, out);
1693

1694 1695
	if (w->reg >= 0)
		ret += snprintf(buf + ret, PAGE_SIZE - ret,
1696 1697
				" - R%d(0x%x) mask 0x%x",
				w->reg, w->reg, w->mask << w->shift);
1698 1699 1700

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

1701 1702 1703 1704
	if (w->sname)
		ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
				w->sname,
				w->active ? "active" : "inactive");
1705 1706

	list_for_each_entry(p, &w->sources, list_sink) {
1707
		if (p->connected && !p->connected(w, p->source))
1708 1709
			continue;

1710 1711
		if (p->connect)
			ret += snprintf(buf + ret, PAGE_SIZE - ret,
1712
					" in  \"%s\" \"%s\"\n",
1713 1714 1715 1716
					p->name ? p->name : "static",
					p->source->name);
	}
	list_for_each_entry(p, &w->sinks, list_source) {
1717 1718 1719
		if (p->connected && !p->connected(w, p->sink))
			continue;

1720 1721
		if (p->connect)
			ret += snprintf(buf + ret, PAGE_SIZE - ret,
1722
					" out \"%s\" \"%s\"\n",
1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733
					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 = {
1734
	.open = simple_open,
1735
	.read = dapm_widget_power_read_file,
1736
	.llseek = default_llseek,
1737 1738
};

1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758
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 已提交
1759
		WARN(1, "Unknown bias_level %d\n", dapm->bias_level);
1760 1761 1762 1763 1764 1765 1766 1767 1768
		level = "Unknown\n";
		break;
	}

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

static const struct file_operations dapm_bias_fops = {
1769
	.open = simple_open,
1770 1771 1772 1773
	.read = dapm_bias_read_file,
	.llseek = default_llseek,
};

1774 1775
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
	struct dentry *parent)
1776 1777 1778
{
	struct dentry *d;

1779 1780 1781
	dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);

	if (!dapm->debugfs_dapm) {
1782
		dev_warn(dapm->dev,
1783
		       "ASoC: Failed to create DAPM debugfs directory\n");
1784
		return;
1785
	}
1786

1787 1788 1789 1790 1791 1792
	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");
1793
}
1794

1795 1796 1797 1798
static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
{
	struct snd_soc_dapm_context *dapm = w->dapm;
	struct dentry *d;
1799

1800 1801 1802 1803 1804 1805 1806 1807 1808 1809
	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);
1810
}
1811

1812 1813 1814 1815 1816
static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
{
	debugfs_remove_recursive(dapm->debugfs_dapm);
}

1817
#else
1818 1819
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
	struct dentry *parent)
1820 1821
{
}
1822 1823 1824 1825 1826

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

1827 1828 1829 1830
static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
{
}

1831 1832
#endif

1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850
/*
 * soc_dapm_connect_path() - Connects or disconnects a path
 * @path: The path to update
 * @connect: The new connect state of the path. True if the path is connected,
 *  false if it is disconneted.
 * @reason: The reason why the path changed (for debugging only)
 */
static void soc_dapm_connect_path(struct snd_soc_dapm_path *path,
	bool connect, const char *reason)
{
	if (path->connect == connect)
		return;

	path->connect = connect;
	dapm_mark_dirty(path->source, reason);
	dapm_mark_dirty(path->sink, reason);
}

1851
/* test and update the power status of a mux widget */
1852
static int soc_dapm_mux_update_power(struct snd_soc_card *card,
1853
				 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
1854 1855 1856
{
	struct snd_soc_dapm_path *path;
	int found = 0;
1857
	bool connect;
1858

1859 1860
	lockdep_assert_held(&card->dapm_mutex);

1861
	/* find dapm widget path assoc with kcontrol */
1862
	dapm_kcontrol_for_each_path(path, kcontrol) {
1863 1864
		found = 1;
		/* we now need to match the string in the enum to the path */
1865 1866 1867 1868 1869 1870
		if (!(strcmp(path->name, e->texts[mux])))
			connect = true;
		else
			connect = false;

		soc_dapm_connect_path(path, connect, "mux update");
1871 1872
	}

1873
	if (found)
1874
		dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
1875

1876
	return found;
1877
}
1878

1879
int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
1880 1881
	struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
	struct snd_soc_dapm_update *update)
1882
{
1883
	struct snd_soc_card *card = dapm->card;
1884 1885
	int ret;

1886
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
1887
	card->update = update;
1888
	ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
1889
	card->update = NULL;
1890
	mutex_unlock(&card->dapm_mutex);
1891
	if (ret > 0)
1892
		soc_dpcm_runtime_update(card);
1893 1894
	return ret;
}
1895
EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
1896

1897
/* test and update the power status of a mixer or switch widget */
1898
static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
1899
				   struct snd_kcontrol *kcontrol, int connect)
1900 1901 1902 1903
{
	struct snd_soc_dapm_path *path;
	int found = 0;

1904 1905
	lockdep_assert_held(&card->dapm_mutex);

1906
	/* find dapm widget path assoc with kcontrol */
1907
	dapm_kcontrol_for_each_path(path, kcontrol) {
1908
		found = 1;
1909
		soc_dapm_connect_path(path, connect, "mixer update");
1910 1911
	}

1912
	if (found)
1913
		dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
1914

1915
	return found;
1916
}
1917

1918
int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
1919 1920
	struct snd_kcontrol *kcontrol, int connect,
	struct snd_soc_dapm_update *update)
1921
{
1922
	struct snd_soc_card *card = dapm->card;
1923 1924
	int ret;

1925
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
1926
	card->update = update;
1927
	ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
1928
	card->update = NULL;
1929
	mutex_unlock(&card->dapm_mutex);
1930
	if (ret > 0)
1931
		soc_dpcm_runtime_update(card);
1932 1933
	return ret;
}
1934
EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
1935

1936
static ssize_t dapm_widget_show_codec(struct snd_soc_codec *codec, char *buf)
1937 1938 1939 1940 1941
{
	struct snd_soc_dapm_widget *w;
	int count = 0;
	char *state = "not set";

1942
	list_for_each_entry(w, &codec->component.card->widgets, list) {
1943 1944
		if (w->dapm != &codec->dapm)
			continue;
1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955

		/* 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:
1956
		case snd_soc_dapm_out_drv:
1957
		case snd_soc_dapm_mixer:
1958
		case snd_soc_dapm_mixer_named_ctl:
1959
		case snd_soc_dapm_supply:
1960
		case snd_soc_dapm_regulator_supply:
1961
		case snd_soc_dapm_clock_supply:
1962 1963 1964 1965 1966 1967 1968 1969 1970
			if (w->name)
				count += sprintf(buf + count, "%s: %s\n",
					w->name, w->power ? "On":"Off");
		break;
		default:
		break;
		}
	}

L
Liam Girdwood 已提交
1971
	switch (codec->dapm.bias_level) {
1972 1973
	case SND_SOC_BIAS_ON:
		state = "On";
1974
		break;
1975 1976
	case SND_SOC_BIAS_PREPARE:
		state = "Prepare";
1977
		break;
1978 1979
	case SND_SOC_BIAS_STANDBY:
		state = "Standby";
1980
		break;
1981 1982
	case SND_SOC_BIAS_OFF:
		state = "Off";
1983 1984 1985 1986 1987 1988 1989
		break;
	}
	count += sprintf(buf + count, "PM State: %s\n", state);

	return count;
}

1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004
/* show dapm widget status in sys fs */
static ssize_t dapm_widget_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
	int i, count = 0;

	for (i = 0; i < rtd->num_codecs; i++) {
		struct snd_soc_codec *codec = rtd->codec_dais[i]->codec;
		count += dapm_widget_show_codec(codec, buf + count);
	}

	return count;
}

2005 2006 2007 2008
static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);

int snd_soc_dapm_sys_add(struct device *dev)
{
2009
	return device_create_file(dev, &dev_attr_dapm_widget);
2010 2011 2012 2013
}

static void snd_soc_dapm_sys_remove(struct device *dev)
{
2014
	device_remove_file(dev, &dev_attr_dapm_widget);
2015 2016
}

2017 2018 2019 2020
static void dapm_free_path(struct snd_soc_dapm_path *path)
{
	list_del(&path->list_sink);
	list_del(&path->list_source);
2021
	list_del(&path->list_kcontrol);
2022 2023 2024 2025
	list_del(&path->list);
	kfree(path);
}

2026
/* free all dapm widgets and resources */
L
Liam Girdwood 已提交
2027
static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
2028 2029 2030 2031
{
	struct snd_soc_dapm_widget *w, *next_w;
	struct snd_soc_dapm_path *p, *next_p;

2032 2033 2034
	list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
		if (w->dapm != dapm)
			continue;
2035
		list_del(&w->list);
2036 2037 2038 2039 2040
		/*
		 * 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.
		 */
2041 2042 2043 2044 2045 2046
		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);

2047
		kfree(w->kcontrols);
2048
		kfree(w->name);
2049 2050 2051 2052
		kfree(w);
	}
}

2053 2054 2055
static struct snd_soc_dapm_widget *dapm_find_widget(
			struct snd_soc_dapm_context *dapm, const char *pin,
			bool search_other_contexts)
2056 2057
{
	struct snd_soc_dapm_widget *w;
2058
	struct snd_soc_dapm_widget *fallback = NULL;
2059

2060
	list_for_each_entry(w, &dapm->card->widgets, list) {
2061
		if (!strcmp(w->name, pin)) {
2062 2063 2064 2065
			if (w->dapm == dapm)
				return w;
			else
				fallback = w;
2066 2067 2068
		}
	}

2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079
	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);

2080 2081
	dapm_assert_locked(dapm);

2082
	if (!w) {
2083
		dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin);
2084
		return -EINVAL;
2085 2086
	}

2087 2088 2089
	if (w->connected != status)
		dapm_mark_dirty(w, "pin configuration");

2090 2091 2092 2093 2094
	w->connected = status;
	if (status == 0)
		w->force = 0;

	return 0;
2095 2096
}

2097
/**
2098
 * snd_soc_dapm_sync_unlocked - scan and power dapm paths
L
Liam Girdwood 已提交
2099
 * @dapm: DAPM context
2100 2101 2102 2103
 *
 * Walks all dapm audio paths and powers widgets according to their
 * stream or path usage.
 *
2104 2105
 * Requires external locking.
 *
2106 2107
 * Returns 0 for success.
 */
2108
int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm)
2109
{
2110 2111 2112 2113 2114 2115 2116
	/*
	 * Suppress early reports (eg, jacks syncing their state) to avoid
	 * silly DAPM runs during card startup.
	 */
	if (!dapm->card || !dapm->card->instantiated)
		return 0;

2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133
	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;

2134
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2135
	ret = snd_soc_dapm_sync_unlocked(dapm);
2136 2137
	mutex_unlock(&dapm->card->dapm_mutex);
	return ret;
2138
}
2139
EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
2140

2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187
/*
 * dapm_update_widget_flags() - Re-compute widget sink and source flags
 * @w: The widget for which to update the flags
 *
 * Some widgets have a dynamic category which depends on which neighbors they
 * are connected to. This function update the category for these widgets.
 *
 * This function must be called whenever a path is added or removed to a widget.
 */
static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w)
{
	struct snd_soc_dapm_path *p;

	switch (w->id) {
	case snd_soc_dapm_input:
		w->is_source = 1;
		list_for_each_entry(p, &w->sources, list_sink) {
			if (p->source->id == snd_soc_dapm_micbias ||
				p->source->id == snd_soc_dapm_mic ||
				p->source->id == snd_soc_dapm_line ||
				p->source->id == snd_soc_dapm_output) {
					w->is_source = 0;
					break;
			}
		}
		break;
	case snd_soc_dapm_output:
		w->is_sink = 1;
		list_for_each_entry(p, &w->sinks, list_source) {
			if (p->sink->id == snd_soc_dapm_spk ||
				p->sink->id == snd_soc_dapm_hp ||
				p->sink->id == snd_soc_dapm_line ||
				p->sink->id == snd_soc_dapm_input) {
					w->is_sink = 0;
					break;
			}
		}
		break;
	case snd_soc_dapm_line:
		w->is_sink = !list_empty(&w->sources);
		w->is_source = !list_empty(&w->sinks);
		break;
	default:
		break;
	}
}

2188 2189 2190 2191 2192
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))
2193 2194
{
	struct snd_soc_dapm_path *path;
2195
	int ret;
2196 2197 2198 2199 2200 2201 2202

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

	path->source = wsource;
	path->sink = wsink;
2203
	path->connected = connected;
2204
	INIT_LIST_HEAD(&path->list);
2205
	INIT_LIST_HEAD(&path->list_kcontrol);
2206 2207 2208
	INIT_LIST_HEAD(&path->list_source);
	INIT_LIST_HEAD(&path->list_sink);

2209 2210 2211
	if (wsource->is_supply || wsink->is_supply)
		path->is_supply = 1;

2212 2213 2214
	/* connect static paths */
	if (control == NULL) {
		path->connect = 1;
2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234
	} else {
		/* connect dynamic paths */
		switch (wsink->id) {
		case snd_soc_dapm_mux:
			ret = dapm_connect_mux(dapm, path, control);
			if (ret != 0)
				goto err;
			break;
		case snd_soc_dapm_switch:
		case snd_soc_dapm_mixer:
		case snd_soc_dapm_mixer_named_ctl:
			ret = dapm_connect_mixer(dapm, path, control);
			if (ret != 0)
				goto err;
			break;
		default:
			dev_err(dapm->dev,
				"Control not supported for path %s -> [%s] -> %s\n",
				wsource->name, control, wsink->name);
			ret = -EINVAL;
2235
			goto err;
2236
		}
2237
	}
2238

2239 2240 2241 2242
	list_add(&path->list, &dapm->card->paths);
	list_add(&path->list_sink, &wsink->sources);
	list_add(&path->list_source, &wsource->sinks);

2243 2244 2245
	dapm_update_widget_flags(wsource);
	dapm_update_widget_flags(wsink);

2246 2247 2248
	dapm_mark_dirty(wsource, "Route added");
	dapm_mark_dirty(wsink, "Route added");

2249
	return 0;
2250 2251 2252 2253
err:
	kfree(path);
	return ret;
}
2254

2255
static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2256
				  const struct snd_soc_dapm_route *route)
2257 2258 2259 2260 2261 2262 2263
{
	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];
2264
	const char *prefix;
2265 2266
	int ret;

2267 2268
	prefix = soc_dapm_prefix(dapm);
	if (prefix) {
2269
		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2270
			 prefix, route->sink);
2271 2272
		sink = prefixed_sink;
		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
2273
			 prefix, route->source);
2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319
		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;
2320
err:
2321
	dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n",
2322
		 source, route->control, sink);
2323 2324
	return ret;
}
2325

2326 2327 2328
static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
				  const struct snd_soc_dapm_route *route)
{
2329
	struct snd_soc_dapm_widget *wsource, *wsink;
2330 2331 2332 2333 2334
	struct snd_soc_dapm_path *path, *p;
	const char *sink;
	const char *source;
	char prefixed_sink[80];
	char prefixed_source[80];
2335
	const char *prefix;
2336 2337 2338

	if (route->control) {
		dev_err(dapm->dev,
2339
			"ASoC: Removal of routes with controls not supported\n");
2340 2341 2342
		return -EINVAL;
	}

2343 2344
	prefix = soc_dapm_prefix(dapm);
	if (prefix) {
2345
		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2346
			 prefix, route->sink);
2347 2348
		sink = prefixed_sink;
		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
2349
			 prefix, route->source);
2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366
		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) {
2367 2368 2369 2370 2371
		wsource = path->source;
		wsink = path->sink;

		dapm_mark_dirty(wsource, "Route removed");
		dapm_mark_dirty(wsink, "Route removed");
2372

2373
		dapm_free_path(path);
2374 2375 2376 2377

		/* Update any path related flags */
		dapm_update_widget_flags(wsource);
		dapm_update_widget_flags(wsink);
2378
	} else {
2379
		dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n",
2380 2381 2382 2383 2384 2385
			 source, sink);
	}

	return 0;
}

2386 2387
/**
 * snd_soc_dapm_add_routes - Add routes between DAPM widgets
L
Liam Girdwood 已提交
2388
 * @dapm: DAPM context
2389 2390 2391 2392 2393 2394 2395 2396 2397 2398
 * @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 已提交
2399
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
2400 2401
			    const struct snd_soc_dapm_route *route, int num)
{
2402
	int i, r, ret = 0;
2403

2404
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2405
	for (i = 0; i < num; i++) {
2406
		r = snd_soc_dapm_add_route(dapm, route);
2407
		if (r < 0) {
2408 2409 2410 2411
			dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n",
				route->source,
				route->control ? route->control : "direct",
				route->sink);
2412
			ret = r;
2413 2414 2415
		}
		route++;
	}
2416
	mutex_unlock(&dapm->card->dapm_mutex);
2417

2418
	return ret;
2419 2420 2421
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);

2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445
/**
 * 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);

2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458
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) {
2459
		dev_err(dapm->dev, "ASoC: Unable to find source %s for weak route\n",
2460 2461 2462 2463 2464
			route->source);
		return -ENODEV;
	}

	if (!sink) {
2465
		dev_err(dapm->dev, "ASoC: Unable to find sink %s for weak route\n",
2466 2467 2468 2469 2470
			route->sink);
		return -ENODEV;
	}

	if (route->control || route->connected)
2471
		dev_warn(dapm->dev, "ASoC: Ignoring control for weak route %s->%s\n",
2472 2473 2474 2475 2476 2477 2478 2479 2480 2481
			 route->source, route->sink);

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

	if (count == 0)
2482
		dev_err(dapm->dev, "ASoC: No path found for weak route %s->%s\n",
2483 2484
			route->source, route->sink);
	if (count > 1)
2485
		dev_warn(dapm->dev, "ASoC: %d paths found for weak route %s->%s\n",
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
			 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;

2513
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2514 2515 2516 2517 2518 2519
	for (i = 0; i < num; i++) {
		err = snd_soc_dapm_weak_route(dapm, route);
		if (err)
			ret = err;
		route++;
	}
2520
	mutex_unlock(&dapm->card->dapm_mutex);
2521 2522 2523 2524 2525

	return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);

2526 2527
/**
 * snd_soc_dapm_new_widgets - add new dapm widgets
L
Liam Girdwood 已提交
2528
 * @dapm: DAPM context
2529 2530 2531 2532 2533
 *
 * Checks the codec for any new dapm widgets and creates them if found.
 *
 * Returns 0 for success.
 */
2534
int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
2535 2536
{
	struct snd_soc_dapm_widget *w;
2537
	unsigned int val;
2538

2539
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2540

2541
	list_for_each_entry(w, &card->widgets, list)
2542 2543 2544 2545
	{
		if (w->new)
			continue;

2546 2547 2548 2549
		if (w->num_kcontrols) {
			w->kcontrols = kzalloc(w->num_kcontrols *
						sizeof(struct snd_kcontrol *),
						GFP_KERNEL);
2550
			if (!w->kcontrols) {
2551
				mutex_unlock(&card->dapm_mutex);
2552
				return -ENOMEM;
2553
			}
2554 2555
		}

2556 2557 2558
		switch(w->id) {
		case snd_soc_dapm_switch:
		case snd_soc_dapm_mixer:
2559
		case snd_soc_dapm_mixer_named_ctl:
2560
			dapm_new_mixer(w);
2561 2562
			break;
		case snd_soc_dapm_mux:
2563
			dapm_new_mux(w);
2564 2565
			break;
		case snd_soc_dapm_pga:
2566
		case snd_soc_dapm_out_drv:
2567
			dapm_new_pga(w);
2568
			break;
2569
		default:
2570 2571
			break;
		}
2572 2573 2574

		/* Read the initial power state from the device */
		if (w->reg >= 0) {
2575
			soc_dapm_read(w->dapm, w->reg, &val);
2576
			val = val >> w->shift;
2577 2578
			val &= w->mask;
			if (val == w->on_val)
2579 2580 2581
				w->power = 1;
		}

2582
		w->new = 1;
2583

2584
		dapm_mark_dirty(w, "new widget");
2585
		dapm_debugfs_add_widget(w);
2586 2587
	}

2588 2589
	dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
	mutex_unlock(&card->dapm_mutex);
2590 2591 2592 2593 2594 2595 2596
	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 已提交
2597
 * @ucontrol: control element information
2598 2599 2600 2601 2602 2603 2604 2605
 *
 * 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)
{
2606 2607
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
	struct snd_soc_card *card = dapm->card;
2608 2609
	struct soc_mixer_control *mc =
		(struct soc_mixer_control *)kcontrol->private_value;
2610
	int reg = mc->reg;
2611
	unsigned int shift = mc->shift;
2612
	int max = mc->max;
2613
	unsigned int mask = (1 << fls(max)) - 1;
2614
	unsigned int invert = mc->invert;
2615
	unsigned int val;
2616
	int ret = 0;
2617 2618

	if (snd_soc_volsw_is_stereo(mc))
2619
		dev_warn(dapm->dev,
2620
			 "ASoC: Control '%s' is stereo, which is not supported\n",
2621
			 kcontrol->id.name);
2622

2623
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2624 2625 2626 2627
	if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) {
		ret = soc_dapm_read(dapm, reg, &val);
		val = (val >> shift) & mask;
	} else {
2628
		val = dapm_kcontrol_get_value(kcontrol);
2629
	}
2630 2631
	mutex_unlock(&card->dapm_mutex);

2632
	if (invert)
2633 2634 2635
		ucontrol->value.integer.value[0] = max - val;
	else
		ucontrol->value.integer.value[0] = val;
2636

2637
	return ret;
2638 2639 2640 2641 2642 2643
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);

/**
 * snd_soc_dapm_put_volsw - dapm mixer set callback
 * @kcontrol: mixer control
M
Mark Brown 已提交
2644
 * @ucontrol: control element information
2645 2646 2647 2648 2649 2650 2651 2652
 *
 * 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)
{
2653 2654
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
	struct snd_soc_card *card = dapm->card;
2655 2656
	struct soc_mixer_control *mc =
		(struct soc_mixer_control *)kcontrol->private_value;
2657
	int reg = mc->reg;
2658
	unsigned int shift = mc->shift;
2659
	int max = mc->max;
2660 2661
	unsigned int mask = (1 << fls(max)) - 1;
	unsigned int invert = mc->invert;
2662
	unsigned int val;
2663
	int connect, change, reg_change = 0;
2664
	struct snd_soc_dapm_update update;
2665
	int ret = 0;
2666

2667
	if (snd_soc_volsw_is_stereo(mc))
2668
		dev_warn(dapm->dev,
2669
			 "ASoC: Control '%s' is stereo, which is not supported\n",
2670 2671
			 kcontrol->id.name);

2672
	val = (ucontrol->value.integer.value[0] & mask);
2673
	connect = !!val;
2674 2675

	if (invert)
P
Philipp Zabel 已提交
2676
		val = max - val;
2677

2678
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2679

2680
	change = dapm_kcontrol_set_value(kcontrol, val);
2681

2682 2683 2684 2685
	if (reg != SND_SOC_NOPM) {
		mask = mask << shift;
		val = val << shift;

2686
		reg_change = soc_dapm_test_bits(dapm, reg, mask, val);
2687 2688 2689 2690 2691 2692 2693 2694 2695
	}

	if (change || reg_change) {
		if (reg_change) {
			update.kcontrol = kcontrol;
			update.reg = reg;
			update.mask = mask;
			update.val = val;
			card->update = &update;
2696
		}
2697
		change |= reg_change;
2698

2699
		ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
2700

2701
		card->update = NULL;
2702 2703
	}

2704
	mutex_unlock(&card->dapm_mutex);
2705 2706 2707 2708

	if (ret > 0)
		soc_dpcm_runtime_update(card);

2709
	return change;
2710 2711 2712 2713 2714 2715
}
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 已提交
2716
 * @ucontrol: control element information
2717 2718 2719 2720 2721 2722 2723 2724
 *
 * 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)
{
2725
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
2726
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2727
	unsigned int reg_val, val;
2728

2729 2730 2731 2732 2733
	if (e->reg != SND_SOC_NOPM) {
		int ret = soc_dapm_read(dapm, e->reg, &reg_val);
		if (ret)
			return ret;
	} else {
2734
		reg_val = dapm_kcontrol_get_value(kcontrol);
2735
	}
P
Peter Ujfalusi 已提交
2736 2737

	val = (reg_val >> e->shift_l) & e->mask;
2738
	ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val);
P
Peter Ujfalusi 已提交
2739 2740
	if (e->shift_l != e->shift_r) {
		val = (reg_val >> e->shift_r) & e->mask;
2741 2742
		val = snd_soc_enum_val_to_item(e, val);
		ucontrol->value.enumerated.item[1] = val;
P
Peter Ujfalusi 已提交
2743 2744
	}

2745
	return 0;
P
Peter Ujfalusi 已提交
2746
}
2747
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
P
Peter Ujfalusi 已提交
2748 2749

/**
2750
 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
P
Peter Ujfalusi 已提交
2751 2752 2753
 * @kcontrol: mixer control
 * @ucontrol: control element information
 *
2754
 * Callback to set the value of a dapm enumerated double mixer control.
P
Peter Ujfalusi 已提交
2755 2756 2757
 *
 * Returns 0 for success.
 */
2758
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
P
Peter Ujfalusi 已提交
2759 2760
	struct snd_ctl_elem_value *ucontrol)
{
2761 2762
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
	struct snd_soc_card *card = dapm->card;
2763
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2764 2765
	unsigned int *item = ucontrol->value.enumerated.item;
	unsigned int val, change;
2766
	unsigned int mask;
2767
	struct snd_soc_dapm_update update;
2768
	int ret = 0;
P
Peter Ujfalusi 已提交
2769

2770
	if (item[0] >= e->items)
P
Peter Ujfalusi 已提交
2771
		return -EINVAL;
2772 2773

	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
P
Peter Ujfalusi 已提交
2774 2775
	mask = e->mask << e->shift_l;
	if (e->shift_l != e->shift_r) {
2776
		if (item[1] > e->items)
P
Peter Ujfalusi 已提交
2777
			return -EINVAL;
2778
		val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_l;
P
Peter Ujfalusi 已提交
2779 2780 2781
		mask |= e->mask << e->shift_r;
	}

2782
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2783

2784
	if (e->reg != SND_SOC_NOPM)
2785
		change = soc_dapm_test_bits(dapm, e->reg, mask, val);
2786 2787 2788
	else
		change = dapm_kcontrol_set_value(kcontrol, val);

2789
	if (change) {
2790 2791 2792 2793 2794 2795 2796
		if (e->reg != SND_SOC_NOPM) {
			update.kcontrol = kcontrol;
			update.reg = e->reg;
			update.mask = mask;
			update.val = val;
			card->update = &update;
		}
2797

2798
		ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e);
2799

2800
		card->update = NULL;
2801
	}
P
Peter Ujfalusi 已提交
2802

2803
	mutex_unlock(&card->dapm_mutex);
2804 2805 2806 2807

	if (ret > 0)
		soc_dpcm_runtime_update(card);

2808
	return change;
P
Peter Ujfalusi 已提交
2809
}
2810
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
P
Peter Ujfalusi 已提交
2811

2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840
/**
 * 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)
{
2841
	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
2842 2843
	const char *pin = (const char *)kcontrol->private_value;

2844
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2845 2846

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

2849
	mutex_unlock(&card->dapm_mutex);
2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863

	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)
{
2864
	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
2865 2866 2867
	const char *pin = (const char *)kcontrol->private_value;

	if (ucontrol->value.integer.value[0])
2868
		snd_soc_dapm_enable_pin(&card->dapm, pin);
2869
	else
2870
		snd_soc_dapm_disable_pin(&card->dapm, pin);
2871

2872
	snd_soc_dapm_sync(&card->dapm);
2873 2874 2875 2876
	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);

2877 2878 2879
static struct snd_soc_dapm_widget *
snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
			 const struct snd_soc_dapm_widget *widget)
2880 2881
{
	struct snd_soc_dapm_widget *w;
2882
	const char *prefix;
2883
	int ret;
2884 2885

	if ((w = dapm_cnew_widget(widget)) == NULL)
2886
		return NULL;
2887

2888 2889
	switch (w->id) {
	case snd_soc_dapm_regulator_supply:
2890 2891 2892
		w->regulator = devm_regulator_get(dapm->dev, w->name);
		if (IS_ERR(w->regulator)) {
			ret = PTR_ERR(w->regulator);
2893
			dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
2894
				w->name, ret);
2895
			return NULL;
2896
		}
2897

2898
		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
2899 2900 2901
			ret = regulator_allow_bypass(w->regulator, true);
			if (ret != 0)
				dev_warn(w->dapm->dev,
2902
					 "ASoC: Failed to bypass %s: %d\n",
2903 2904
					 w->name, ret);
		}
2905
		break;
2906
	case snd_soc_dapm_clock_supply:
2907
#ifdef CONFIG_CLKDEV_LOOKUP
M
Mark Brown 已提交
2908
		w->clk = devm_clk_get(dapm->dev, w->name);
2909 2910
		if (IS_ERR(w->clk)) {
			ret = PTR_ERR(w->clk);
2911
			dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
2912 2913 2914
				w->name, ret);
			return NULL;
		}
2915 2916 2917
#else
		return NULL;
#endif
2918
		break;
2919 2920 2921
	default:
		break;
	}
2922

2923 2924 2925
	prefix = soc_dapm_prefix(dapm);
	if (prefix)
		w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name);
2926 2927 2928
	else
		w->name = kasprintf(GFP_KERNEL, "%s", widget->name);

2929 2930
	if (w->name == NULL) {
		kfree(w);
2931
		return NULL;
2932 2933
	}

2934
	switch (w->id) {
2935 2936 2937
	case snd_soc_dapm_mic:
	case snd_soc_dapm_input:
		w->is_source = 1;
2938 2939
		w->power_check = dapm_generic_check_power;
		break;
2940 2941 2942 2943
	case snd_soc_dapm_spk:
	case snd_soc_dapm_hp:
	case snd_soc_dapm_output:
		w->is_sink = 1;
2944 2945
		w->power_check = dapm_generic_check_power;
		break;
2946 2947 2948 2949 2950 2951 2952 2953 2954
	case snd_soc_dapm_vmid:
	case snd_soc_dapm_siggen:
		w->is_source = 1;
		w->power_check = dapm_always_on_check_power;
		break;
	case snd_soc_dapm_mux:
	case snd_soc_dapm_switch:
	case snd_soc_dapm_mixer:
	case snd_soc_dapm_mixer_named_ctl:
2955 2956 2957 2958
	case snd_soc_dapm_adc:
	case snd_soc_dapm_aif_out:
	case snd_soc_dapm_dac:
	case snd_soc_dapm_aif_in:
2959 2960 2961 2962
	case snd_soc_dapm_pga:
	case snd_soc_dapm_out_drv:
	case snd_soc_dapm_micbias:
	case snd_soc_dapm_line:
2963
	case snd_soc_dapm_dai_link:
2964 2965
	case snd_soc_dapm_dai_out:
	case snd_soc_dapm_dai_in:
2966 2967 2968
		w->power_check = dapm_generic_check_power;
		break;
	case snd_soc_dapm_supply:
2969
	case snd_soc_dapm_regulator_supply:
2970
	case snd_soc_dapm_clock_supply:
2971
	case snd_soc_dapm_kcontrol:
2972
		w->is_supply = 1;
2973 2974 2975 2976 2977 2978 2979
		w->power_check = dapm_supply_check_power;
		break;
	default:
		w->power_check = dapm_always_on_check_power;
		break;
	}

L
Liam Girdwood 已提交
2980
	w->dapm = dapm;
2981 2982
	if (dapm->component)
		w->codec = dapm->component->codec;
2983 2984 2985
	INIT_LIST_HEAD(&w->sources);
	INIT_LIST_HEAD(&w->sinks);
	INIT_LIST_HEAD(&w->list);
2986
	INIT_LIST_HEAD(&w->dirty);
2987
	list_add(&w->list, &dapm->card->widgets);
2988 2989 2990

	/* machine layer set ups unconnected pins and insertions */
	w->connected = 1;
2991
	return w;
2992 2993
}

2994 2995
/**
 * snd_soc_dapm_new_controls - create new dapm controls
L
Liam Girdwood 已提交
2996
 * @dapm: DAPM context
2997 2998 2999 3000 3001 3002 3003
 * @widget: widget array
 * @num: number of widgets
 *
 * Creates new DAPM controls based upon the templates.
 *
 * Returns 0 for success else error.
 */
L
Liam Girdwood 已提交
3004
int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
3005 3006 3007
	const struct snd_soc_dapm_widget *widget,
	int num)
{
3008 3009
	struct snd_soc_dapm_widget *w;
	int i;
3010
	int ret = 0;
3011

3012
	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
3013
	for (i = 0; i < num; i++) {
3014 3015
		w = snd_soc_dapm_new_control(dapm, widget);
		if (!w) {
3016
			dev_err(dapm->dev,
3017 3018
				"ASoC: Failed to create DAPM control %s\n",
				widget->name);
3019 3020
			ret = -ENOMEM;
			break;
3021
		}
3022 3023
		widget++;
	}
3024
	mutex_unlock(&dapm->card->dapm_mutex);
3025
	return ret;
3026 3027 3028
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);

3029 3030 3031 3032 3033 3034 3035
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;
3036
	struct snd_pcm_hw_params *params = NULL;
3037 3038 3039
	u64 fmt;
	int ret;

3040 3041 3042
	if (WARN_ON(!config) ||
	    WARN_ON(list_empty(&w->sources) || list_empty(&w->sinks)))
		return -EINVAL;
3043 3044 3045 3046 3047 3048 3049

	/* 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);

3050 3051 3052 3053
	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;
3054 3055 3056 3057 3058 3059 3060 3061

	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 {
3062
		dev_warn(w->dapm->dev, "ASoC: Invalid format %llx specified\n",
3063 3064 3065 3066 3067
			 config->formats);
		fmt = 0;
	}

	/* Currently very limited parameter selection */
3068 3069 3070 3071 3072 3073
	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);
3074

3075
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min =
3076
		config->rate_min;
3077
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max =
3078 3079
		config->rate_max;

3080
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min
3081
		= config->channels_min;
3082
	hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max
3083 3084 3085 3086 3087 3088
		= config->channels_max;

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

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
3089 3090 3091 3092
		substream.stream = SNDRV_PCM_STREAM_CAPTURE;
		ret = soc_dai_hw_params(&substream, params, source);
		if (ret < 0)
			goto out;
3093

3094 3095 3096 3097
		substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
		ret = soc_dai_hw_params(&substream, params, sink);
		if (ret < 0)
			goto out;
3098 3099 3100
		break;

	case SND_SOC_DAPM_POST_PMU:
3101 3102
		ret = snd_soc_dai_digital_mute(sink, 0,
					       SNDRV_PCM_STREAM_PLAYBACK);
3103
		if (ret != 0 && ret != -ENOTSUPP)
3104
			dev_warn(sink->dev, "ASoC: Failed to unmute: %d\n", ret);
3105
		ret = 0;
3106 3107 3108
		break;

	case SND_SOC_DAPM_PRE_PMD:
3109 3110
		ret = snd_soc_dai_digital_mute(sink, 1,
					       SNDRV_PCM_STREAM_PLAYBACK);
3111
		if (ret != 0 && ret != -ENOTSUPP)
3112
			dev_warn(sink->dev, "ASoC: Failed to mute: %d\n", ret);
3113
		ret = 0;
3114 3115 3116
		break;

	default:
T
Takashi Iwai 已提交
3117
		WARN(1, "Unknown event %d\n", event);
3118 3119 3120
		return -EINVAL;
	}

3121 3122 3123
out:
	kfree(params);
	return ret;
3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134
}

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_widget template;
	struct snd_soc_dapm_widget *w;
	size_t len;
	char *link_name;
3135
	int ret;
3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150

	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;

3151
	dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name);
3152 3153 3154

	w = snd_soc_dapm_new_control(&card->dapm, &template);
	if (!w) {
3155
		dev_err(card->dev, "ASoC: Failed to create %s widget\n",
3156 3157 3158 3159 3160 3161
			link_name);
		return -ENOMEM;
	}

	w->params = params;

3162 3163 3164 3165
	ret = snd_soc_dapm_add_path(&card->dapm, source, w, NULL, NULL);
	if (ret)
		return ret;
	return snd_soc_dapm_add_path(&card->dapm, w, sink, NULL, NULL);
3166 3167
}

3168 3169
int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
				 struct snd_soc_dai *dai)
3170
{
3171
	struct snd_soc_dapm_widget template;
3172 3173
	struct snd_soc_dapm_widget *w;

3174 3175 3176 3177 3178 3179
	WARN_ON(dapm->dev != dai->dev);

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

	if (dai->driver->playback.stream_name) {
3180
		template.id = snd_soc_dapm_dai_in;
3181 3182 3183
		template.name = dai->driver->playback.stream_name;
		template.sname = dai->driver->playback.stream_name;

3184
		dev_dbg(dai->dev, "ASoC: adding %s widget\n",
3185 3186 3187 3188
			template.name);

		w = snd_soc_dapm_new_control(dapm, &template);
		if (!w) {
3189
			dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
3190
				dai->driver->playback.stream_name);
3191
			return -ENOMEM;
3192 3193 3194 3195 3196 3197 3198
		}

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

	if (dai->driver->capture.stream_name) {
3199
		template.id = snd_soc_dapm_dai_out;
3200 3201 3202
		template.name = dai->driver->capture.stream_name;
		template.sname = dai->driver->capture.stream_name;

3203
		dev_dbg(dai->dev, "ASoC: adding %s widget\n",
3204 3205 3206 3207
			template.name);

		w = snd_soc_dapm_new_control(dapm, &template);
		if (!w) {
3208
			dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
3209
				dai->driver->capture.stream_name);
3210
			return -ENOMEM;
3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222
		}

		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;
3223
	struct snd_soc_dapm_widget *src, *sink;
3224 3225 3226 3227
	struct snd_soc_dai *dai;

	/* For each DAI widget... */
	list_for_each_entry(dai_w, &card->widgets, list) {
3228 3229 3230 3231 3232
		switch (dai_w->id) {
		case snd_soc_dapm_dai_in:
		case snd_soc_dapm_dai_out:
			break;
		default:
3233
			continue;
3234
		}
3235 3236 3237 3238 3239 3240 3241 3242

		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;

3243 3244 3245
			switch (w->id) {
			case snd_soc_dapm_dai_in:
			case snd_soc_dapm_dai_out:
3246
				continue;
3247 3248 3249
			default:
				break;
			}
3250

R
Russell King 已提交
3251
			if (!w->sname || !strstr(w->sname, dai_w->name))
3252 3253
				continue;

3254 3255 3256 3257 3258 3259
			if (dai_w->id == snd_soc_dapm_dai_in) {
				src = dai_w;
				sink = w;
			} else {
				src = w;
				sink = dai_w;
3260
			}
3261 3262
			dev_dbg(dai->dev, "%s -> %s\n", src->name, sink->name);
			snd_soc_dapm_add_path(w->dapm, src, sink, NULL, NULL);
3263 3264 3265
		}
	}

3266 3267
	return 0;
}
3268

3269 3270
static void dapm_connect_dai_link_widgets(struct snd_soc_card *card,
					  struct snd_soc_pcm_runtime *rtd)
3271
{
3272
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
3273
	struct snd_soc_dapm_widget *sink, *source;
3274 3275
	int i;

3276 3277
	for (i = 0; i < rtd->num_codecs; i++) {
		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
3278 3279 3280 3281 3282 3283 3284 3285

		/* 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) {
3286 3287
			source = cpu_dai->playback_widget;
			sink = codec_dai->playback_widget;
3288
			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
3289 3290
				cpu_dai->component->name, source->name,
				codec_dai->component->name, sink->name);
3291

3292 3293
			snd_soc_dapm_add_path(&card->dapm, source, sink,
				NULL, NULL);
3294 3295 3296 3297
		}

		/* connect BE DAI capture if widgets are valid */
		if (codec_dai->capture_widget && cpu_dai->capture_widget) {
3298 3299
			source = codec_dai->capture_widget;
			sink = cpu_dai->capture_widget;
3300
			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
3301 3302
				codec_dai->component->name, source->name,
				cpu_dai->component->name, sink->name);
3303

3304 3305
			snd_soc_dapm_add_path(&card->dapm, source, sink,
				NULL, NULL);
3306 3307 3308 3309
		}
	}
}

3310
static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
3311
	int event)
3312
{
3313
	struct snd_soc_dapm_widget *w;
3314

3315 3316 3317 3318
	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
		w = dai->playback_widget;
	else
		w = dai->capture_widget;
3319

3320 3321
	if (w) {
		dapm_mark_dirty(w, "stream event");
3322 3323 3324

		switch (event) {
		case SND_SOC_DAPM_STREAM_START:
3325
			w->active = 1;
3326 3327
			break;
		case SND_SOC_DAPM_STREAM_STOP:
3328
			w->active = 0;
3329 3330 3331 3332 3333 3334 3335
			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;
		}
3336 3337 3338 3339 3340

		if (w->id == snd_soc_dapm_dai_in)
			w->is_source = w->active;
		else
			w->is_sink = w->active;
3341
	}
3342
}
3343

3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
{
	struct snd_soc_pcm_runtime *rtd = card->rtd;
	int i;

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

		/*
		 * dynamic FE links have no fixed DAI mapping.
		 * CODEC<->CODEC links have no direct connection.
		 */
		if (rtd->dai_link->dynamic || rtd->dai_link->params)
			continue;

		dapm_connect_dai_link_widgets(card, rtd);
	}
}

3364 3365 3366
static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
	int event)
{
3367 3368
	int i;

3369
	soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event);
3370 3371
	for (i = 0; i < rtd->num_codecs; i++)
		soc_dapm_dai_stream_event(rtd->codec_dais[i], stream, event);
3372

3373
	dapm_power_widgets(rtd->card, event);
L
Liam Girdwood 已提交
3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386
}

/**
 * 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.
 */
3387 3388
void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
			      int event)
L
Liam Girdwood 已提交
3389
{
3390
	struct snd_soc_card *card = rtd->card;
L
Liam Girdwood 已提交
3391

3392
	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3393
	soc_dapm_stream_event(rtd, stream, event);
3394
	mutex_unlock(&card->dapm_mutex);
3395 3396
}

3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416
/**
 * 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);

3417
/**
3418
 * snd_soc_dapm_enable_pin - enable pin.
L
Liam Girdwood 已提交
3419
 * @dapm: DAPM context
3420
 * @pin: pin name
3421
 *
M
Mark Brown 已提交
3422
 * Enables input/output pin and its parents or children widgets iff there is
3423
 * a valid audio route and active audio stream.
3424
 *
3425 3426
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
3427
 */
L
Liam Girdwood 已提交
3428
int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
3429
{
3430 3431 3432 3433 3434 3435 3436 3437 3438
	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;
3439 3440
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
3441

3442
/**
3443
 * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
L
Liam Girdwood 已提交
3444
 * @dapm: DAPM context
3445 3446 3447 3448 3449 3450
 * @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.
 *
3451 3452
 * Requires external locking.
 *
3453 3454 3455
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
3456 3457
int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
					 const char *pin)
3458
{
3459
	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
3460

3461
	if (!w) {
3462
		dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
3463
		return -EINVAL;
3464 3465
	}

3466
	dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin);
3467 3468
	w->connected = 1;
	w->force = 1;
3469
	dapm_mark_dirty(w, "force enable");
3470

3471
	return 0;
3472
}
3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499
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;
}
3500 3501
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);

3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520
/**
 * 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);

3521 3522
/**
 * snd_soc_dapm_disable_pin - disable pin.
L
Liam Girdwood 已提交
3523
 * @dapm: DAPM context
3524 3525
 * @pin: pin name
 *
M
Mark Brown 已提交
3526
 * Disables input/output pin and its parents or children widgets.
3527
 *
3528 3529 3530
 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
 * do any widget power switching.
 */
L
Liam Girdwood 已提交
3531 3532
int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
			     const char *pin)
3533
{
3534 3535 3536 3537 3538 3539 3540 3541 3542
	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;
3543
}
3544
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
3545

3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568
/**
 * 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);

3569 3570
/**
 * snd_soc_dapm_nc_pin - permanently disable pin.
L
Liam Girdwood 已提交
3571
 * @dapm: DAPM context
3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582
 * @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 已提交
3583
int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
3584
{
3585 3586 3587 3588 3589 3590 3591 3592 3593
	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;
3594 3595 3596
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);

3597
/**
3598
 * snd_soc_dapm_get_pin_status - get audio pin status
L
Liam Girdwood 已提交
3599
 * @dapm: DAPM context
3600
 * @pin: audio signal pin endpoint (or start point)
3601
 *
3602
 * Get audio pin status - connected or disconnected.
3603
 *
3604
 * Returns 1 for connected otherwise 0.
3605
 */
L
Liam Girdwood 已提交
3606 3607
int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
				const char *pin)
3608
{
3609
	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
3610

3611 3612
	if (w)
		return w->connected;
3613

3614 3615
	return 0;
}
3616
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
3617

3618 3619
/**
 * snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint
L
Liam Girdwood 已提交
3620
 * @dapm: DAPM context
3621 3622 3623 3624 3625 3626 3627 3628
 * @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 已提交
3629 3630
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
				const char *pin)
3631
{
3632
	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, false);
3633

3634
	if (!w) {
3635
		dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
3636
		return -EINVAL;
3637 3638
	}

3639 3640 3641
	w->ignore_suspend = 1;

	return 0;
3642 3643 3644
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);

3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679
/**
 * dapm_is_external_path() - Checks if a path is a external path
 * @card: The card the path belongs to
 * @path: The path to check
 *
 * Returns true if the path is either between two different DAPM contexts or
 * between two external pins of the same DAPM context. Otherwise returns
 * false.
 */
static bool dapm_is_external_path(struct snd_soc_card *card,
	struct snd_soc_dapm_path *path)
{
	dev_dbg(card->dev,
		"... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n",
		path->source->name, path->source->id, path->source->dapm,
		path->sink->name, path->sink->id, path->sink->dapm);

	/* Connection between two different DAPM contexts */
	if (path->source->dapm != path->sink->dapm)
		return true;

	/* Loopback connection from external pin to external pin */
	if (path->sink->id == snd_soc_dapm_input) {
		switch (path->source->id) {
		case snd_soc_dapm_output:
		case snd_soc_dapm_micbias:
			return true;
		default:
			break;
		}
	}

	return false;
}

3680 3681 3682 3683 3684
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;

3685 3686 3687 3688
	list_for_each_entry(p, &w->sources, list_sink) {
		if (dapm_is_external_path(card, p))
			return true;
	}
3689

3690 3691 3692
	list_for_each_entry(p, &w->sinks, list_source) {
		if (dapm_is_external_path(card, p))
			return true;
3693 3694 3695 3696 3697 3698
	}

	return false;
}

/**
3699 3700
 * snd_soc_dapm_auto_nc_pins - call snd_soc_dapm_nc_pin for unused pins
 * @card: The card whose pins should be processed
3701
 *
3702 3703 3704 3705
 * Automatically call snd_soc_dapm_nc_pin() for any external pins in the card
 * which are unused. Pins are used if they are connected externally to a
 * component, whether that be to some other device, or a loop-back connection to
 * the component itself.
3706
 */
3707
void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card)
3708 3709 3710
{
	struct snd_soc_dapm_widget *w;

3711
	dev_dbg(card->dev, "ASoC: Auto NC: DAPMs: card:%p\n", &card->dapm);
3712 3713 3714 3715 3716 3717

	list_for_each_entry(w, &card->widgets, list) {
		switch (w->id) {
		case snd_soc_dapm_input:
		case snd_soc_dapm_output:
		case snd_soc_dapm_micbias:
3718
			dev_dbg(card->dev, "ASoC: Auto NC: Checking widget %s\n",
3719 3720
				w->name);
			if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
3721
				dev_dbg(card->dev,
3722
					"... Not in map; disabling\n");
3723
				snd_soc_dapm_nc_pin(w->dapm, w->name);
3724 3725 3726 3727 3728 3729 3730 3731
			}
			break;
		default:
			break;
		}
	}
}

3732 3733
/**
 * snd_soc_dapm_free - free dapm resources
3734
 * @dapm: DAPM context
3735 3736 3737
 *
 * Free all dapm widgets and resources.
 */
L
Liam Girdwood 已提交
3738
void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm)
3739
{
L
Liam Girdwood 已提交
3740
	snd_soc_dapm_sys_remove(dapm->dev);
3741
	dapm_debugfs_cleanup(dapm);
L
Liam Girdwood 已提交
3742
	dapm_free_widgets(dapm);
3743
	list_del(&dapm->list);
3744 3745 3746
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_free);

3747
static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm)
M
Mark Brown 已提交
3748
{
3749
	struct snd_soc_card *card = dapm->card;
M
Mark Brown 已提交
3750 3751 3752 3753
	struct snd_soc_dapm_widget *w;
	LIST_HEAD(down_list);
	int powerdown = 0;

3754 3755
	mutex_lock(&card->dapm_mutex);

3756 3757 3758
	list_for_each_entry(w, &dapm->card->widgets, list) {
		if (w->dapm != dapm)
			continue;
M
Mark Brown 已提交
3759
		if (w->power) {
3760
			dapm_seq_insert(w, &down_list, false);
3761
			w->power = 0;
M
Mark Brown 已提交
3762 3763 3764 3765 3766 3767 3768 3769
			powerdown = 1;
		}
	}

	/* If there were no widgets to power down we're already in
	 * standby.
	 */
	if (powerdown) {
3770 3771 3772
		if (dapm->bias_level == SND_SOC_BIAS_ON)
			snd_soc_dapm_set_bias_level(dapm,
						    SND_SOC_BIAS_PREPARE);
3773
		dapm_seq_run(card, &down_list, 0, false);
3774 3775 3776
		if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
			snd_soc_dapm_set_bias_level(dapm,
						    SND_SOC_BIAS_STANDBY);
M
Mark Brown 已提交
3777
	}
3778 3779

	mutex_unlock(&card->dapm_mutex);
3780 3781 3782 3783 3784 3785 3786
}

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

3789
	list_for_each_entry(dapm, &card->dapm_list, list) {
3790 3791 3792 3793 3794 3795
		if (dapm != &card->dapm) {
			soc_dapm_shutdown_dapm(dapm);
			if (dapm->bias_level == SND_SOC_BIAS_STANDBY)
				snd_soc_dapm_set_bias_level(dapm,
							    SND_SOC_BIAS_OFF);
		}
L
Liam Girdwood 已提交
3796
	}
3797 3798 3799 3800 3801

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

3804
/* Module information */
3805
MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
3806 3807
MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
MODULE_LICENSE("GPL");