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