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