Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/soc/soc-dapm.c
10814 views
1
/*
2
* soc-dapm.c -- ALSA SoC Dynamic Audio Power Management
3
*
4
* Copyright 2005 Wolfson Microelectronics PLC.
5
* Author: Liam Girdwood <[email protected]>
6
*
7
* This program is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU General Public License as published by the
9
* Free Software Foundation; either version 2 of the License, or (at your
10
* option) any later version.
11
*
12
* Features:
13
* o Changes power status of internal codec blocks depending on the
14
* dynamic configuration of codec internal audio paths and active
15
* DACs/ADCs.
16
* o Platform power domain - can support external components i.e. amps and
17
* mic/meadphone insertion events.
18
* o Automatic Mic Bias support
19
* o Jack insertion power event initiation - e.g. hp insertion will enable
20
* sinks, dacs, etc
21
* o Delayed powerdown of audio susbsystem to reduce pops between a quick
22
* device reopen.
23
*
24
* Todo:
25
* o DAPM power change sequencing - allow for configurable per
26
* codec sequences.
27
* o Support for analogue bias optimisation.
28
* o Support for reduced codec oversampling rates.
29
* o Support for reduced codec bias currents.
30
*/
31
32
#include <linux/module.h>
33
#include <linux/moduleparam.h>
34
#include <linux/init.h>
35
#include <linux/async.h>
36
#include <linux/delay.h>
37
#include <linux/pm.h>
38
#include <linux/bitops.h>
39
#include <linux/platform_device.h>
40
#include <linux/jiffies.h>
41
#include <linux/debugfs.h>
42
#include <linux/slab.h>
43
#include <sound/core.h>
44
#include <sound/pcm.h>
45
#include <sound/pcm_params.h>
46
#include <sound/soc.h>
47
#include <sound/initval.h>
48
49
#include <trace/events/asoc.h>
50
51
/* dapm power sequences - make this per codec in the future */
52
static int dapm_up_seq[] = {
53
[snd_soc_dapm_pre] = 0,
54
[snd_soc_dapm_supply] = 1,
55
[snd_soc_dapm_micbias] = 2,
56
[snd_soc_dapm_aif_in] = 3,
57
[snd_soc_dapm_aif_out] = 3,
58
[snd_soc_dapm_mic] = 4,
59
[snd_soc_dapm_mux] = 5,
60
[snd_soc_dapm_virt_mux] = 5,
61
[snd_soc_dapm_value_mux] = 5,
62
[snd_soc_dapm_dac] = 6,
63
[snd_soc_dapm_mixer] = 7,
64
[snd_soc_dapm_mixer_named_ctl] = 7,
65
[snd_soc_dapm_pga] = 8,
66
[snd_soc_dapm_adc] = 9,
67
[snd_soc_dapm_out_drv] = 10,
68
[snd_soc_dapm_hp] = 10,
69
[snd_soc_dapm_spk] = 10,
70
[snd_soc_dapm_post] = 11,
71
};
72
73
static int dapm_down_seq[] = {
74
[snd_soc_dapm_pre] = 0,
75
[snd_soc_dapm_adc] = 1,
76
[snd_soc_dapm_hp] = 2,
77
[snd_soc_dapm_spk] = 2,
78
[snd_soc_dapm_out_drv] = 2,
79
[snd_soc_dapm_pga] = 4,
80
[snd_soc_dapm_mixer_named_ctl] = 5,
81
[snd_soc_dapm_mixer] = 5,
82
[snd_soc_dapm_dac] = 6,
83
[snd_soc_dapm_mic] = 7,
84
[snd_soc_dapm_micbias] = 8,
85
[snd_soc_dapm_mux] = 9,
86
[snd_soc_dapm_virt_mux] = 9,
87
[snd_soc_dapm_value_mux] = 9,
88
[snd_soc_dapm_aif_in] = 10,
89
[snd_soc_dapm_aif_out] = 10,
90
[snd_soc_dapm_supply] = 11,
91
[snd_soc_dapm_post] = 12,
92
};
93
94
static void pop_wait(u32 pop_time)
95
{
96
if (pop_time)
97
schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
98
}
99
100
static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
101
{
102
va_list args;
103
char *buf;
104
105
if (!pop_time)
106
return;
107
108
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
109
if (buf == NULL)
110
return;
111
112
va_start(args, fmt);
113
vsnprintf(buf, PAGE_SIZE, fmt, args);
114
dev_info(dev, "%s", buf);
115
va_end(args);
116
117
kfree(buf);
118
}
119
120
/* create a new dapm widget */
121
static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
122
const struct snd_soc_dapm_widget *_widget)
123
{
124
return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
125
}
126
127
/**
128
* snd_soc_dapm_set_bias_level - set the bias level for the system
129
* @dapm: DAPM context
130
* @level: level to configure
131
*
132
* Configure the bias (power) levels for the SoC audio device.
133
*
134
* Returns 0 for success else error.
135
*/
136
static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
137
enum snd_soc_bias_level level)
138
{
139
struct snd_soc_card *card = dapm->card;
140
int ret = 0;
141
142
switch (level) {
143
case SND_SOC_BIAS_ON:
144
dev_dbg(dapm->dev, "Setting full bias\n");
145
break;
146
case SND_SOC_BIAS_PREPARE:
147
dev_dbg(dapm->dev, "Setting bias prepare\n");
148
break;
149
case SND_SOC_BIAS_STANDBY:
150
dev_dbg(dapm->dev, "Setting standby bias\n");
151
break;
152
case SND_SOC_BIAS_OFF:
153
dev_dbg(dapm->dev, "Setting bias off\n");
154
break;
155
default:
156
dev_err(dapm->dev, "Setting invalid bias %d\n", level);
157
return -EINVAL;
158
}
159
160
trace_snd_soc_bias_level_start(card, level);
161
162
if (card && card->set_bias_level)
163
ret = card->set_bias_level(card, level);
164
if (ret == 0) {
165
if (dapm->codec && dapm->codec->driver->set_bias_level)
166
ret = dapm->codec->driver->set_bias_level(dapm->codec, level);
167
else
168
dapm->bias_level = level;
169
}
170
if (ret == 0) {
171
if (card && card->set_bias_level_post)
172
ret = card->set_bias_level_post(card, level);
173
}
174
175
trace_snd_soc_bias_level_done(card, level);
176
177
return ret;
178
}
179
180
/* set up initial codec paths */
181
static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
182
struct snd_soc_dapm_path *p, int i)
183
{
184
switch (w->id) {
185
case snd_soc_dapm_switch:
186
case snd_soc_dapm_mixer:
187
case snd_soc_dapm_mixer_named_ctl: {
188
int val;
189
struct soc_mixer_control *mc = (struct soc_mixer_control *)
190
w->kcontrol_news[i].private_value;
191
unsigned int reg = mc->reg;
192
unsigned int shift = mc->shift;
193
int max = mc->max;
194
unsigned int mask = (1 << fls(max)) - 1;
195
unsigned int invert = mc->invert;
196
197
val = snd_soc_read(w->codec, reg);
198
val = (val >> shift) & mask;
199
200
if ((invert && !val) || (!invert && val))
201
p->connect = 1;
202
else
203
p->connect = 0;
204
}
205
break;
206
case snd_soc_dapm_mux: {
207
struct soc_enum *e = (struct soc_enum *)
208
w->kcontrol_news[i].private_value;
209
int val, item, bitmask;
210
211
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
212
;
213
val = snd_soc_read(w->codec, e->reg);
214
item = (val >> e->shift_l) & (bitmask - 1);
215
216
p->connect = 0;
217
for (i = 0; i < e->max; i++) {
218
if (!(strcmp(p->name, e->texts[i])) && item == i)
219
p->connect = 1;
220
}
221
}
222
break;
223
case snd_soc_dapm_virt_mux: {
224
struct soc_enum *e = (struct soc_enum *)
225
w->kcontrol_news[i].private_value;
226
227
p->connect = 0;
228
/* since a virtual mux has no backing registers to
229
* decide which path to connect, it will try to match
230
* with the first enumeration. This is to ensure
231
* that the default mux choice (the first) will be
232
* correctly powered up during initialization.
233
*/
234
if (!strcmp(p->name, e->texts[0]))
235
p->connect = 1;
236
}
237
break;
238
case snd_soc_dapm_value_mux: {
239
struct soc_enum *e = (struct soc_enum *)
240
w->kcontrol_news[i].private_value;
241
int val, item;
242
243
val = snd_soc_read(w->codec, e->reg);
244
val = (val >> e->shift_l) & e->mask;
245
for (item = 0; item < e->max; item++) {
246
if (val == e->values[item])
247
break;
248
}
249
250
p->connect = 0;
251
for (i = 0; i < e->max; i++) {
252
if (!(strcmp(p->name, e->texts[i])) && item == i)
253
p->connect = 1;
254
}
255
}
256
break;
257
/* does not effect routing - always connected */
258
case snd_soc_dapm_pga:
259
case snd_soc_dapm_out_drv:
260
case snd_soc_dapm_output:
261
case snd_soc_dapm_adc:
262
case snd_soc_dapm_input:
263
case snd_soc_dapm_dac:
264
case snd_soc_dapm_micbias:
265
case snd_soc_dapm_vmid:
266
case snd_soc_dapm_supply:
267
case snd_soc_dapm_aif_in:
268
case snd_soc_dapm_aif_out:
269
p->connect = 1;
270
break;
271
/* does effect routing - dynamically connected */
272
case snd_soc_dapm_hp:
273
case snd_soc_dapm_mic:
274
case snd_soc_dapm_spk:
275
case snd_soc_dapm_line:
276
case snd_soc_dapm_pre:
277
case snd_soc_dapm_post:
278
p->connect = 0;
279
break;
280
}
281
}
282
283
/* connect mux widget to its interconnecting audio paths */
284
static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
285
struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
286
struct snd_soc_dapm_path *path, const char *control_name,
287
const struct snd_kcontrol_new *kcontrol)
288
{
289
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
290
int i;
291
292
for (i = 0; i < e->max; i++) {
293
if (!(strcmp(control_name, e->texts[i]))) {
294
list_add(&path->list, &dapm->card->paths);
295
list_add(&path->list_sink, &dest->sources);
296
list_add(&path->list_source, &src->sinks);
297
path->name = (char*)e->texts[i];
298
dapm_set_path_status(dest, path, 0);
299
return 0;
300
}
301
}
302
303
return -ENODEV;
304
}
305
306
/* connect mixer widget to its interconnecting audio paths */
307
static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,
308
struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
309
struct snd_soc_dapm_path *path, const char *control_name)
310
{
311
int i;
312
313
/* search for mixer kcontrol */
314
for (i = 0; i < dest->num_kcontrols; i++) {
315
if (!strcmp(control_name, dest->kcontrol_news[i].name)) {
316
list_add(&path->list, &dapm->card->paths);
317
list_add(&path->list_sink, &dest->sources);
318
list_add(&path->list_source, &src->sinks);
319
path->name = dest->kcontrol_news[i].name;
320
dapm_set_path_status(dest, path, i);
321
return 0;
322
}
323
}
324
return -ENODEV;
325
}
326
327
static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
328
struct snd_soc_dapm_widget *kcontrolw,
329
const struct snd_kcontrol_new *kcontrol_new,
330
struct snd_kcontrol **kcontrol)
331
{
332
struct snd_soc_dapm_widget *w;
333
int i;
334
335
*kcontrol = NULL;
336
337
list_for_each_entry(w, &dapm->card->widgets, list) {
338
if (w == kcontrolw || w->dapm != kcontrolw->dapm)
339
continue;
340
for (i = 0; i < w->num_kcontrols; i++) {
341
if (&w->kcontrol_news[i] == kcontrol_new) {
342
if (w->kcontrols)
343
*kcontrol = w->kcontrols[i];
344
return 1;
345
}
346
}
347
}
348
349
return 0;
350
}
351
352
/* create new dapm mixer control */
353
static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
354
{
355
struct snd_soc_dapm_context *dapm = w->dapm;
356
int i, ret = 0;
357
size_t name_len, prefix_len;
358
struct snd_soc_dapm_path *path;
359
struct snd_card *card = dapm->card->snd_card;
360
const char *prefix;
361
struct snd_soc_dapm_widget_list *wlist;
362
size_t wlistsize;
363
364
if (dapm->codec)
365
prefix = dapm->codec->name_prefix;
366
else
367
prefix = NULL;
368
369
if (prefix)
370
prefix_len = strlen(prefix) + 1;
371
else
372
prefix_len = 0;
373
374
/* add kcontrol */
375
for (i = 0; i < w->num_kcontrols; i++) {
376
377
/* match name */
378
list_for_each_entry(path, &w->sources, list_sink) {
379
380
/* mixer/mux paths name must match control name */
381
if (path->name != (char *)w->kcontrol_news[i].name)
382
continue;
383
384
wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
385
sizeof(struct snd_soc_dapm_widget *),
386
wlist = kzalloc(wlistsize, GFP_KERNEL);
387
if (wlist == NULL) {
388
dev_err(dapm->dev,
389
"asoc: can't allocate widget list for %s\n",
390
w->name);
391
return -ENOMEM;
392
}
393
wlist->num_widgets = 1;
394
wlist->widgets[0] = w;
395
396
/* add dapm control with long name.
397
* for dapm_mixer this is the concatenation of the
398
* mixer and kcontrol name.
399
* for dapm_mixer_named_ctl this is simply the
400
* kcontrol name.
401
*/
402
name_len = strlen(w->kcontrol_news[i].name) + 1;
403
if (w->id != snd_soc_dapm_mixer_named_ctl)
404
name_len += 1 + strlen(w->name);
405
406
path->long_name = kmalloc(name_len, GFP_KERNEL);
407
408
if (path->long_name == NULL) {
409
kfree(wlist);
410
return -ENOMEM;
411
}
412
413
switch (w->id) {
414
default:
415
/* The control will get a prefix from
416
* the control creation process but
417
* we're also using the same prefix
418
* for widgets so cut the prefix off
419
* the front of the widget name.
420
*/
421
snprintf(path->long_name, name_len, "%s %s",
422
w->name + prefix_len,
423
w->kcontrol_news[i].name);
424
break;
425
case snd_soc_dapm_mixer_named_ctl:
426
snprintf(path->long_name, name_len, "%s",
427
w->kcontrol_news[i].name);
428
break;
429
}
430
431
path->long_name[name_len - 1] = '\0';
432
433
path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
434
wlist, path->long_name,
435
prefix);
436
ret = snd_ctl_add(card, path->kcontrol);
437
if (ret < 0) {
438
dev_err(dapm->dev,
439
"asoc: failed to add dapm kcontrol %s: %d\n",
440
path->long_name, ret);
441
kfree(wlist);
442
kfree(path->long_name);
443
path->long_name = NULL;
444
return ret;
445
}
446
w->kcontrols[i] = path->kcontrol;
447
}
448
}
449
return ret;
450
}
451
452
/* create new dapm mux control */
453
static int dapm_new_mux(struct snd_soc_dapm_widget *w)
454
{
455
struct snd_soc_dapm_context *dapm = w->dapm;
456
struct snd_soc_dapm_path *path = NULL;
457
struct snd_kcontrol *kcontrol;
458
struct snd_card *card = dapm->card->snd_card;
459
const char *prefix;
460
size_t prefix_len;
461
int ret;
462
struct snd_soc_dapm_widget_list *wlist;
463
int shared, wlistentries;
464
size_t wlistsize;
465
char *name;
466
467
if (w->num_kcontrols != 1) {
468
dev_err(dapm->dev,
469
"asoc: mux %s has incorrect number of controls\n",
470
w->name);
471
return -EINVAL;
472
}
473
474
shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[0],
475
&kcontrol);
476
if (kcontrol) {
477
wlist = kcontrol->private_data;
478
wlistentries = wlist->num_widgets + 1;
479
} else {
480
wlist = NULL;
481
wlistentries = 1;
482
}
483
wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
484
wlistentries * sizeof(struct snd_soc_dapm_widget *),
485
wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
486
if (wlist == NULL) {
487
dev_err(dapm->dev,
488
"asoc: can't allocate widget list for %s\n", w->name);
489
return -ENOMEM;
490
}
491
wlist->num_widgets = wlistentries;
492
wlist->widgets[wlistentries - 1] = w;
493
494
if (!kcontrol) {
495
if (dapm->codec)
496
prefix = dapm->codec->name_prefix;
497
else
498
prefix = NULL;
499
500
if (shared) {
501
name = w->kcontrol_news[0].name;
502
prefix_len = 0;
503
} else {
504
name = w->name;
505
if (prefix)
506
prefix_len = strlen(prefix) + 1;
507
else
508
prefix_len = 0;
509
}
510
511
/*
512
* The control will get a prefix from the control creation
513
* process but we're also using the same prefix for widgets so
514
* cut the prefix off the front of the widget name.
515
*/
516
kcontrol = snd_soc_cnew(&w->kcontrol_news[0], wlist,
517
name + prefix_len, prefix);
518
ret = snd_ctl_add(card, kcontrol);
519
if (ret < 0) {
520
dev_err(dapm->dev,
521
"asoc: failed to add kcontrol %s\n", w->name);
522
kfree(wlist);
523
return ret;
524
}
525
}
526
527
kcontrol->private_data = wlist;
528
529
w->kcontrols[0] = kcontrol;
530
531
list_for_each_entry(path, &w->sources, list_sink)
532
path->kcontrol = kcontrol;
533
534
return 0;
535
}
536
537
/* create new dapm volume control */
538
static int dapm_new_pga(struct snd_soc_dapm_widget *w)
539
{
540
if (w->num_kcontrols)
541
dev_err(w->dapm->dev,
542
"asoc: PGA controls not supported: '%s'\n", w->name);
543
544
return 0;
545
}
546
547
/* reset 'walked' bit for each dapm path */
548
static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm)
549
{
550
struct snd_soc_dapm_path *p;
551
552
list_for_each_entry(p, &dapm->card->paths, list)
553
p->walked = 0;
554
}
555
556
/* We implement power down on suspend by checking the power state of
557
* the ALSA card - when we are suspending the ALSA state for the card
558
* is set to D3.
559
*/
560
static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
561
{
562
int level = snd_power_get_state(widget->dapm->card->snd_card);
563
564
switch (level) {
565
case SNDRV_CTL_POWER_D3hot:
566
case SNDRV_CTL_POWER_D3cold:
567
if (widget->ignore_suspend)
568
dev_dbg(widget->dapm->dev, "%s ignoring suspend\n",
569
widget->name);
570
return widget->ignore_suspend;
571
default:
572
return 1;
573
}
574
}
575
576
/*
577
* Recursively check for a completed path to an active or physically connected
578
* output widget. Returns number of complete paths.
579
*/
580
static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
581
{
582
struct snd_soc_dapm_path *path;
583
int con = 0;
584
585
if (widget->id == snd_soc_dapm_supply)
586
return 0;
587
588
switch (widget->id) {
589
case snd_soc_dapm_adc:
590
case snd_soc_dapm_aif_out:
591
if (widget->active)
592
return snd_soc_dapm_suspend_check(widget);
593
default:
594
break;
595
}
596
597
if (widget->connected) {
598
/* connected pin ? */
599
if (widget->id == snd_soc_dapm_output && !widget->ext)
600
return snd_soc_dapm_suspend_check(widget);
601
602
/* connected jack or spk ? */
603
if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
604
(widget->id == snd_soc_dapm_line && !list_empty(&widget->sources)))
605
return snd_soc_dapm_suspend_check(widget);
606
}
607
608
list_for_each_entry(path, &widget->sinks, list_source) {
609
if (path->walked)
610
continue;
611
612
if (path->sink && path->connect) {
613
path->walked = 1;
614
con += is_connected_output_ep(path->sink);
615
}
616
}
617
618
return con;
619
}
620
621
/*
622
* Recursively check for a completed path to an active or physically connected
623
* input widget. Returns number of complete paths.
624
*/
625
static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
626
{
627
struct snd_soc_dapm_path *path;
628
int con = 0;
629
630
if (widget->id == snd_soc_dapm_supply)
631
return 0;
632
633
/* active stream ? */
634
switch (widget->id) {
635
case snd_soc_dapm_dac:
636
case snd_soc_dapm_aif_in:
637
if (widget->active)
638
return snd_soc_dapm_suspend_check(widget);
639
default:
640
break;
641
}
642
643
if (widget->connected) {
644
/* connected pin ? */
645
if (widget->id == snd_soc_dapm_input && !widget->ext)
646
return snd_soc_dapm_suspend_check(widget);
647
648
/* connected VMID/Bias for lower pops */
649
if (widget->id == snd_soc_dapm_vmid)
650
return snd_soc_dapm_suspend_check(widget);
651
652
/* connected jack ? */
653
if (widget->id == snd_soc_dapm_mic ||
654
(widget->id == snd_soc_dapm_line && !list_empty(&widget->sinks)))
655
return snd_soc_dapm_suspend_check(widget);
656
}
657
658
list_for_each_entry(path, &widget->sources, list_sink) {
659
if (path->walked)
660
continue;
661
662
if (path->source && path->connect) {
663
path->walked = 1;
664
con += is_connected_input_ep(path->source);
665
}
666
}
667
668
return con;
669
}
670
671
/*
672
* Handler for generic register modifier widget.
673
*/
674
int dapm_reg_event(struct snd_soc_dapm_widget *w,
675
struct snd_kcontrol *kcontrol, int event)
676
{
677
unsigned int val;
678
679
if (SND_SOC_DAPM_EVENT_ON(event))
680
val = w->on_val;
681
else
682
val = w->off_val;
683
684
snd_soc_update_bits(w->codec, -(w->reg + 1),
685
w->mask << w->shift, val << w->shift);
686
687
return 0;
688
}
689
EXPORT_SYMBOL_GPL(dapm_reg_event);
690
691
/* Generic check to see if a widget should be powered.
692
*/
693
static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
694
{
695
int in, out;
696
697
in = is_connected_input_ep(w);
698
dapm_clear_walk(w->dapm);
699
out = is_connected_output_ep(w);
700
dapm_clear_walk(w->dapm);
701
return out != 0 && in != 0;
702
}
703
704
/* Check to see if an ADC has power */
705
static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
706
{
707
int in;
708
709
if (w->active) {
710
in = is_connected_input_ep(w);
711
dapm_clear_walk(w->dapm);
712
return in != 0;
713
} else {
714
return dapm_generic_check_power(w);
715
}
716
}
717
718
/* Check to see if a DAC has power */
719
static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
720
{
721
int out;
722
723
if (w->active) {
724
out = is_connected_output_ep(w);
725
dapm_clear_walk(w->dapm);
726
return out != 0;
727
} else {
728
return dapm_generic_check_power(w);
729
}
730
}
731
732
/* Check to see if a power supply is needed */
733
static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
734
{
735
struct snd_soc_dapm_path *path;
736
int power = 0;
737
738
/* Check if one of our outputs is connected */
739
list_for_each_entry(path, &w->sinks, list_source) {
740
if (path->connected &&
741
!path->connected(path->source, path->sink))
742
continue;
743
744
if (!path->sink)
745
continue;
746
747
if (path->sink->force) {
748
power = 1;
749
break;
750
}
751
752
if (path->sink->power_check &&
753
path->sink->power_check(path->sink)) {
754
power = 1;
755
break;
756
}
757
}
758
759
dapm_clear_walk(w->dapm);
760
761
return power;
762
}
763
764
static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
765
struct snd_soc_dapm_widget *b,
766
bool power_up)
767
{
768
int *sort;
769
770
if (power_up)
771
sort = dapm_up_seq;
772
else
773
sort = dapm_down_seq;
774
775
if (sort[a->id] != sort[b->id])
776
return sort[a->id] - sort[b->id];
777
if (a->subseq != b->subseq) {
778
if (power_up)
779
return a->subseq - b->subseq;
780
else
781
return b->subseq - a->subseq;
782
}
783
if (a->reg != b->reg)
784
return a->reg - b->reg;
785
if (a->dapm != b->dapm)
786
return (unsigned long)a->dapm - (unsigned long)b->dapm;
787
788
return 0;
789
}
790
791
/* Insert a widget in order into a DAPM power sequence. */
792
static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
793
struct list_head *list,
794
bool power_up)
795
{
796
struct snd_soc_dapm_widget *w;
797
798
list_for_each_entry(w, list, power_list)
799
if (dapm_seq_compare(new_widget, w, power_up) < 0) {
800
list_add_tail(&new_widget->power_list, &w->power_list);
801
return;
802
}
803
804
list_add_tail(&new_widget->power_list, list);
805
}
806
807
static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm,
808
struct snd_soc_dapm_widget *w, int event)
809
{
810
struct snd_soc_card *card = dapm->card;
811
const char *ev_name;
812
int power, ret;
813
814
switch (event) {
815
case SND_SOC_DAPM_PRE_PMU:
816
ev_name = "PRE_PMU";
817
power = 1;
818
break;
819
case SND_SOC_DAPM_POST_PMU:
820
ev_name = "POST_PMU";
821
power = 1;
822
break;
823
case SND_SOC_DAPM_PRE_PMD:
824
ev_name = "PRE_PMD";
825
power = 0;
826
break;
827
case SND_SOC_DAPM_POST_PMD:
828
ev_name = "POST_PMD";
829
power = 0;
830
break;
831
default:
832
BUG();
833
return;
834
}
835
836
if (w->power != power)
837
return;
838
839
if (w->event && (w->event_flags & event)) {
840
pop_dbg(dapm->dev, card->pop_time, "pop test : %s %s\n",
841
w->name, ev_name);
842
trace_snd_soc_dapm_widget_event_start(w, event);
843
ret = w->event(w, NULL, event);
844
trace_snd_soc_dapm_widget_event_done(w, event);
845
if (ret < 0)
846
pr_err("%s: %s event failed: %d\n",
847
ev_name, w->name, ret);
848
}
849
}
850
851
/* Apply the coalesced changes from a DAPM sequence */
852
static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
853
struct list_head *pending)
854
{
855
struct snd_soc_card *card = dapm->card;
856
struct snd_soc_dapm_widget *w;
857
int reg, power;
858
unsigned int value = 0;
859
unsigned int mask = 0;
860
unsigned int cur_mask;
861
862
reg = list_first_entry(pending, struct snd_soc_dapm_widget,
863
power_list)->reg;
864
865
list_for_each_entry(w, pending, power_list) {
866
cur_mask = 1 << w->shift;
867
BUG_ON(reg != w->reg);
868
869
if (w->invert)
870
power = !w->power;
871
else
872
power = w->power;
873
874
mask |= cur_mask;
875
if (power)
876
value |= cur_mask;
877
878
pop_dbg(dapm->dev, card->pop_time,
879
"pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
880
w->name, reg, value, mask);
881
882
/* Check for events */
883
dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMU);
884
dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMD);
885
}
886
887
if (reg >= 0) {
888
pop_dbg(dapm->dev, card->pop_time,
889
"pop test : Applying 0x%x/0x%x to %x in %dms\n",
890
value, mask, reg, card->pop_time);
891
pop_wait(card->pop_time);
892
snd_soc_update_bits(dapm->codec, reg, mask, value);
893
}
894
895
list_for_each_entry(w, pending, power_list) {
896
dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMU);
897
dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMD);
898
}
899
}
900
901
/* Apply a DAPM power sequence.
902
*
903
* We walk over a pre-sorted list of widgets to apply power to. In
904
* order to minimise the number of writes to the device required
905
* multiple widgets will be updated in a single write where possible.
906
* Currently anything that requires more than a single write is not
907
* handled.
908
*/
909
static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
910
struct list_head *list, int event, bool power_up)
911
{
912
struct snd_soc_dapm_widget *w, *n;
913
LIST_HEAD(pending);
914
int cur_sort = -1;
915
int cur_subseq = -1;
916
int cur_reg = SND_SOC_NOPM;
917
struct snd_soc_dapm_context *cur_dapm = NULL;
918
int ret, i;
919
int *sort;
920
921
if (power_up)
922
sort = dapm_up_seq;
923
else
924
sort = dapm_down_seq;
925
926
list_for_each_entry_safe(w, n, list, power_list) {
927
ret = 0;
928
929
/* Do we need to apply any queued changes? */
930
if (sort[w->id] != cur_sort || w->reg != cur_reg ||
931
w->dapm != cur_dapm || w->subseq != cur_subseq) {
932
if (!list_empty(&pending))
933
dapm_seq_run_coalesced(cur_dapm, &pending);
934
935
if (cur_dapm && cur_dapm->seq_notifier) {
936
for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
937
if (sort[i] == cur_sort)
938
cur_dapm->seq_notifier(cur_dapm,
939
i,
940
cur_subseq);
941
}
942
943
INIT_LIST_HEAD(&pending);
944
cur_sort = -1;
945
cur_subseq = -1;
946
cur_reg = SND_SOC_NOPM;
947
cur_dapm = NULL;
948
}
949
950
switch (w->id) {
951
case snd_soc_dapm_pre:
952
if (!w->event)
953
list_for_each_entry_safe_continue(w, n, list,
954
power_list);
955
956
if (event == SND_SOC_DAPM_STREAM_START)
957
ret = w->event(w,
958
NULL, SND_SOC_DAPM_PRE_PMU);
959
else if (event == SND_SOC_DAPM_STREAM_STOP)
960
ret = w->event(w,
961
NULL, SND_SOC_DAPM_PRE_PMD);
962
break;
963
964
case snd_soc_dapm_post:
965
if (!w->event)
966
list_for_each_entry_safe_continue(w, n, list,
967
power_list);
968
969
if (event == SND_SOC_DAPM_STREAM_START)
970
ret = w->event(w,
971
NULL, SND_SOC_DAPM_POST_PMU);
972
else if (event == SND_SOC_DAPM_STREAM_STOP)
973
ret = w->event(w,
974
NULL, SND_SOC_DAPM_POST_PMD);
975
break;
976
977
default:
978
/* Queue it up for application */
979
cur_sort = sort[w->id];
980
cur_subseq = w->subseq;
981
cur_reg = w->reg;
982
cur_dapm = w->dapm;
983
list_move(&w->power_list, &pending);
984
break;
985
}
986
987
if (ret < 0)
988
dev_err(w->dapm->dev,
989
"Failed to apply widget power: %d\n", ret);
990
}
991
992
if (!list_empty(&pending))
993
dapm_seq_run_coalesced(cur_dapm, &pending);
994
995
if (cur_dapm && cur_dapm->seq_notifier) {
996
for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
997
if (sort[i] == cur_sort)
998
cur_dapm->seq_notifier(cur_dapm,
999
i, cur_subseq);
1000
}
1001
}
1002
1003
static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
1004
{
1005
struct snd_soc_dapm_update *update = dapm->update;
1006
struct snd_soc_dapm_widget *w;
1007
int ret;
1008
1009
if (!update)
1010
return;
1011
1012
w = update->widget;
1013
1014
if (w->event &&
1015
(w->event_flags & SND_SOC_DAPM_PRE_REG)) {
1016
ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
1017
if (ret != 0)
1018
pr_err("%s DAPM pre-event failed: %d\n",
1019
w->name, ret);
1020
}
1021
1022
ret = snd_soc_update_bits(w->codec, update->reg, update->mask,
1023
update->val);
1024
if (ret < 0)
1025
pr_err("%s DAPM update failed: %d\n", w->name, ret);
1026
1027
if (w->event &&
1028
(w->event_flags & SND_SOC_DAPM_POST_REG)) {
1029
ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
1030
if (ret != 0)
1031
pr_err("%s DAPM post-event failed: %d\n",
1032
w->name, ret);
1033
}
1034
}
1035
1036
/* Async callback run prior to DAPM sequences - brings to _PREPARE if
1037
* they're changing state.
1038
*/
1039
static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
1040
{
1041
struct snd_soc_dapm_context *d = data;
1042
int ret;
1043
1044
if (d->dev_power && d->bias_level == SND_SOC_BIAS_OFF) {
1045
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
1046
if (ret != 0)
1047
dev_err(d->dev,
1048
"Failed to turn on bias: %d\n", ret);
1049
}
1050
1051
/* If we're changing to all on or all off then prepare */
1052
if ((d->dev_power && d->bias_level == SND_SOC_BIAS_STANDBY) ||
1053
(!d->dev_power && d->bias_level == SND_SOC_BIAS_ON)) {
1054
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);
1055
if (ret != 0)
1056
dev_err(d->dev,
1057
"Failed to prepare bias: %d\n", ret);
1058
}
1059
}
1060
1061
/* Async callback run prior to DAPM sequences - brings to their final
1062
* state.
1063
*/
1064
static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
1065
{
1066
struct snd_soc_dapm_context *d = data;
1067
int ret;
1068
1069
/* If we just powered the last thing off drop to standby bias */
1070
if (d->bias_level == SND_SOC_BIAS_PREPARE && !d->dev_power) {
1071
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
1072
if (ret != 0)
1073
dev_err(d->dev, "Failed to apply standby bias: %d\n",
1074
ret);
1075
}
1076
1077
/* If we're in standby and can support bias off then do that */
1078
if (d->bias_level == SND_SOC_BIAS_STANDBY && d->idle_bias_off) {
1079
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
1080
if (ret != 0)
1081
dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
1082
}
1083
1084
/* If we just powered up then move to active bias */
1085
if (d->bias_level == SND_SOC_BIAS_PREPARE && d->dev_power) {
1086
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON);
1087
if (ret != 0)
1088
dev_err(d->dev, "Failed to apply active bias: %d\n",
1089
ret);
1090
}
1091
}
1092
1093
/*
1094
* Scan each dapm widget for complete audio path.
1095
* A complete path is a route that has valid endpoints i.e.:-
1096
*
1097
* o DAC to output pin.
1098
* o Input Pin to ADC.
1099
* o Input pin to Output pin (bypass, sidetone)
1100
* o DAC to ADC (loopback).
1101
*/
1102
static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1103
{
1104
struct snd_soc_card *card = dapm->card;
1105
struct snd_soc_dapm_widget *w;
1106
struct snd_soc_dapm_context *d;
1107
LIST_HEAD(up_list);
1108
LIST_HEAD(down_list);
1109
LIST_HEAD(async_domain);
1110
int power;
1111
1112
trace_snd_soc_dapm_start(card);
1113
1114
list_for_each_entry(d, &card->dapm_list, list)
1115
if (d->n_widgets || d->codec == NULL)
1116
d->dev_power = 0;
1117
1118
/* Check which widgets we need to power and store them in
1119
* lists indicating if they should be powered up or down.
1120
*/
1121
list_for_each_entry(w, &card->widgets, list) {
1122
switch (w->id) {
1123
case snd_soc_dapm_pre:
1124
dapm_seq_insert(w, &down_list, false);
1125
break;
1126
case snd_soc_dapm_post:
1127
dapm_seq_insert(w, &up_list, true);
1128
break;
1129
1130
default:
1131
if (!w->power_check)
1132
continue;
1133
1134
if (!w->force)
1135
power = w->power_check(w);
1136
else
1137
power = 1;
1138
if (power)
1139
w->dapm->dev_power = 1;
1140
1141
if (w->power == power)
1142
continue;
1143
1144
trace_snd_soc_dapm_widget_power(w, power);
1145
1146
if (power)
1147
dapm_seq_insert(w, &up_list, true);
1148
else
1149
dapm_seq_insert(w, &down_list, false);
1150
1151
w->power = power;
1152
break;
1153
}
1154
}
1155
1156
/* If there are no DAPM widgets then try to figure out power from the
1157
* event type.
1158
*/
1159
if (!dapm->n_widgets) {
1160
switch (event) {
1161
case SND_SOC_DAPM_STREAM_START:
1162
case SND_SOC_DAPM_STREAM_RESUME:
1163
dapm->dev_power = 1;
1164
break;
1165
case SND_SOC_DAPM_STREAM_STOP:
1166
dapm->dev_power = !!dapm->codec->active;
1167
break;
1168
case SND_SOC_DAPM_STREAM_SUSPEND:
1169
dapm->dev_power = 0;
1170
break;
1171
case SND_SOC_DAPM_STREAM_NOP:
1172
switch (dapm->bias_level) {
1173
case SND_SOC_BIAS_STANDBY:
1174
case SND_SOC_BIAS_OFF:
1175
dapm->dev_power = 0;
1176
break;
1177
default:
1178
dapm->dev_power = 1;
1179
break;
1180
}
1181
break;
1182
default:
1183
break;
1184
}
1185
}
1186
1187
/* Force all contexts in the card to the same bias state */
1188
power = 0;
1189
list_for_each_entry(d, &card->dapm_list, list)
1190
if (d->dev_power)
1191
power = 1;
1192
list_for_each_entry(d, &card->dapm_list, list)
1193
d->dev_power = power;
1194
1195
1196
/* Run all the bias changes in parallel */
1197
list_for_each_entry(d, &dapm->card->dapm_list, list)
1198
async_schedule_domain(dapm_pre_sequence_async, d,
1199
&async_domain);
1200
async_synchronize_full_domain(&async_domain);
1201
1202
/* Power down widgets first; try to avoid amplifying pops. */
1203
dapm_seq_run(dapm, &down_list, event, false);
1204
1205
dapm_widget_update(dapm);
1206
1207
/* Now power up. */
1208
dapm_seq_run(dapm, &up_list, event, true);
1209
1210
/* Run all the bias changes in parallel */
1211
list_for_each_entry(d, &dapm->card->dapm_list, list)
1212
async_schedule_domain(dapm_post_sequence_async, d,
1213
&async_domain);
1214
async_synchronize_full_domain(&async_domain);
1215
1216
pop_dbg(dapm->dev, card->pop_time,
1217
"DAPM sequencing finished, waiting %dms\n", card->pop_time);
1218
pop_wait(card->pop_time);
1219
1220
trace_snd_soc_dapm_done(card);
1221
1222
return 0;
1223
}
1224
1225
#ifdef CONFIG_DEBUG_FS
1226
static int dapm_widget_power_open_file(struct inode *inode, struct file *file)
1227
{
1228
file->private_data = inode->i_private;
1229
return 0;
1230
}
1231
1232
static ssize_t dapm_widget_power_read_file(struct file *file,
1233
char __user *user_buf,
1234
size_t count, loff_t *ppos)
1235
{
1236
struct snd_soc_dapm_widget *w = file->private_data;
1237
char *buf;
1238
int in, out;
1239
ssize_t ret;
1240
struct snd_soc_dapm_path *p = NULL;
1241
1242
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
1243
if (!buf)
1244
return -ENOMEM;
1245
1246
in = is_connected_input_ep(w);
1247
dapm_clear_walk(w->dapm);
1248
out = is_connected_output_ep(w);
1249
dapm_clear_walk(w->dapm);
1250
1251
ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d",
1252
w->name, w->power ? "On" : "Off", in, out);
1253
1254
if (w->reg >= 0)
1255
ret += snprintf(buf + ret, PAGE_SIZE - ret,
1256
" - R%d(0x%x) bit %d",
1257
w->reg, w->reg, w->shift);
1258
1259
ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
1260
1261
if (w->sname)
1262
ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
1263
w->sname,
1264
w->active ? "active" : "inactive");
1265
1266
list_for_each_entry(p, &w->sources, list_sink) {
1267
if (p->connected && !p->connected(w, p->sink))
1268
continue;
1269
1270
if (p->connect)
1271
ret += snprintf(buf + ret, PAGE_SIZE - ret,
1272
" in \"%s\" \"%s\"\n",
1273
p->name ? p->name : "static",
1274
p->source->name);
1275
}
1276
list_for_each_entry(p, &w->sinks, list_source) {
1277
if (p->connected && !p->connected(w, p->sink))
1278
continue;
1279
1280
if (p->connect)
1281
ret += snprintf(buf + ret, PAGE_SIZE - ret,
1282
" out \"%s\" \"%s\"\n",
1283
p->name ? p->name : "static",
1284
p->sink->name);
1285
}
1286
1287
ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
1288
1289
kfree(buf);
1290
return ret;
1291
}
1292
1293
static const struct file_operations dapm_widget_power_fops = {
1294
.open = dapm_widget_power_open_file,
1295
.read = dapm_widget_power_read_file,
1296
.llseek = default_llseek,
1297
};
1298
1299
static int dapm_bias_open_file(struct inode *inode, struct file *file)
1300
{
1301
file->private_data = inode->i_private;
1302
return 0;
1303
}
1304
1305
static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,
1306
size_t count, loff_t *ppos)
1307
{
1308
struct snd_soc_dapm_context *dapm = file->private_data;
1309
char *level;
1310
1311
switch (dapm->bias_level) {
1312
case SND_SOC_BIAS_ON:
1313
level = "On\n";
1314
break;
1315
case SND_SOC_BIAS_PREPARE:
1316
level = "Prepare\n";
1317
break;
1318
case SND_SOC_BIAS_STANDBY:
1319
level = "Standby\n";
1320
break;
1321
case SND_SOC_BIAS_OFF:
1322
level = "Off\n";
1323
break;
1324
default:
1325
BUG();
1326
level = "Unknown\n";
1327
break;
1328
}
1329
1330
return simple_read_from_buffer(user_buf, count, ppos, level,
1331
strlen(level));
1332
}
1333
1334
static const struct file_operations dapm_bias_fops = {
1335
.open = dapm_bias_open_file,
1336
.read = dapm_bias_read_file,
1337
.llseek = default_llseek,
1338
};
1339
1340
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
1341
struct dentry *parent)
1342
{
1343
struct dentry *d;
1344
1345
dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);
1346
1347
if (!dapm->debugfs_dapm) {
1348
printk(KERN_WARNING
1349
"Failed to create DAPM debugfs directory\n");
1350
return;
1351
}
1352
1353
d = debugfs_create_file("bias_level", 0444,
1354
dapm->debugfs_dapm, dapm,
1355
&dapm_bias_fops);
1356
if (!d)
1357
dev_warn(dapm->dev,
1358
"ASoC: Failed to create bias level debugfs file\n");
1359
}
1360
1361
static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
1362
{
1363
struct snd_soc_dapm_context *dapm = w->dapm;
1364
struct dentry *d;
1365
1366
if (!dapm->debugfs_dapm || !w->name)
1367
return;
1368
1369
d = debugfs_create_file(w->name, 0444,
1370
dapm->debugfs_dapm, w,
1371
&dapm_widget_power_fops);
1372
if (!d)
1373
dev_warn(w->dapm->dev,
1374
"ASoC: Failed to create %s debugfs file\n",
1375
w->name);
1376
}
1377
1378
static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
1379
{
1380
debugfs_remove_recursive(dapm->debugfs_dapm);
1381
}
1382
1383
#else
1384
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
1385
struct dentry *parent)
1386
{
1387
}
1388
1389
static inline void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
1390
{
1391
}
1392
1393
static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
1394
{
1395
}
1396
1397
#endif
1398
1399
/* test and update the power status of a mux widget */
1400
static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1401
struct snd_kcontrol *kcontrol, int change,
1402
int mux, struct soc_enum *e)
1403
{
1404
struct snd_soc_dapm_path *path;
1405
int found = 0;
1406
1407
if (widget->id != snd_soc_dapm_mux &&
1408
widget->id != snd_soc_dapm_virt_mux &&
1409
widget->id != snd_soc_dapm_value_mux)
1410
return -ENODEV;
1411
1412
if (!change)
1413
return 0;
1414
1415
/* find dapm widget path assoc with kcontrol */
1416
list_for_each_entry(path, &widget->dapm->card->paths, list) {
1417
if (path->kcontrol != kcontrol)
1418
continue;
1419
1420
if (!path->name || !e->texts[mux])
1421
continue;
1422
1423
found = 1;
1424
/* we now need to match the string in the enum to the path */
1425
if (!(strcmp(path->name, e->texts[mux])))
1426
path->connect = 1; /* new connection */
1427
else
1428
path->connect = 0; /* old connection must be powered down */
1429
}
1430
1431
if (found)
1432
dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
1433
1434
return 0;
1435
}
1436
1437
/* test and update the power status of a mixer or switch widget */
1438
static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1439
struct snd_kcontrol *kcontrol, int connect)
1440
{
1441
struct snd_soc_dapm_path *path;
1442
int found = 0;
1443
1444
if (widget->id != snd_soc_dapm_mixer &&
1445
widget->id != snd_soc_dapm_mixer_named_ctl &&
1446
widget->id != snd_soc_dapm_switch)
1447
return -ENODEV;
1448
1449
/* find dapm widget path assoc with kcontrol */
1450
list_for_each_entry(path, &widget->dapm->card->paths, list) {
1451
if (path->kcontrol != kcontrol)
1452
continue;
1453
1454
/* found, now check type */
1455
found = 1;
1456
path->connect = connect;
1457
break;
1458
}
1459
1460
if (found)
1461
dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
1462
1463
return 0;
1464
}
1465
1466
/* show dapm widget status in sys fs */
1467
static ssize_t dapm_widget_show(struct device *dev,
1468
struct device_attribute *attr, char *buf)
1469
{
1470
struct snd_soc_pcm_runtime *rtd =
1471
container_of(dev, struct snd_soc_pcm_runtime, dev);
1472
struct snd_soc_codec *codec =rtd->codec;
1473
struct snd_soc_dapm_widget *w;
1474
int count = 0;
1475
char *state = "not set";
1476
1477
list_for_each_entry(w, &codec->card->widgets, list) {
1478
if (w->dapm != &codec->dapm)
1479
continue;
1480
1481
/* only display widgets that burnm power */
1482
switch (w->id) {
1483
case snd_soc_dapm_hp:
1484
case snd_soc_dapm_mic:
1485
case snd_soc_dapm_spk:
1486
case snd_soc_dapm_line:
1487
case snd_soc_dapm_micbias:
1488
case snd_soc_dapm_dac:
1489
case snd_soc_dapm_adc:
1490
case snd_soc_dapm_pga:
1491
case snd_soc_dapm_out_drv:
1492
case snd_soc_dapm_mixer:
1493
case snd_soc_dapm_mixer_named_ctl:
1494
case snd_soc_dapm_supply:
1495
if (w->name)
1496
count += sprintf(buf + count, "%s: %s\n",
1497
w->name, w->power ? "On":"Off");
1498
break;
1499
default:
1500
break;
1501
}
1502
}
1503
1504
switch (codec->dapm.bias_level) {
1505
case SND_SOC_BIAS_ON:
1506
state = "On";
1507
break;
1508
case SND_SOC_BIAS_PREPARE:
1509
state = "Prepare";
1510
break;
1511
case SND_SOC_BIAS_STANDBY:
1512
state = "Standby";
1513
break;
1514
case SND_SOC_BIAS_OFF:
1515
state = "Off";
1516
break;
1517
}
1518
count += sprintf(buf + count, "PM State: %s\n", state);
1519
1520
return count;
1521
}
1522
1523
static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
1524
1525
int snd_soc_dapm_sys_add(struct device *dev)
1526
{
1527
return device_create_file(dev, &dev_attr_dapm_widget);
1528
}
1529
1530
static void snd_soc_dapm_sys_remove(struct device *dev)
1531
{
1532
device_remove_file(dev, &dev_attr_dapm_widget);
1533
}
1534
1535
/* free all dapm widgets and resources */
1536
static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
1537
{
1538
struct snd_soc_dapm_widget *w, *next_w;
1539
struct snd_soc_dapm_path *p, *next_p;
1540
1541
list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
1542
if (w->dapm != dapm)
1543
continue;
1544
list_del(&w->list);
1545
/*
1546
* remove source and sink paths associated to this widget.
1547
* While removing the path, remove reference to it from both
1548
* source and sink widgets so that path is removed only once.
1549
*/
1550
list_for_each_entry_safe(p, next_p, &w->sources, list_sink) {
1551
list_del(&p->list_sink);
1552
list_del(&p->list_source);
1553
list_del(&p->list);
1554
kfree(p->long_name);
1555
kfree(p);
1556
}
1557
list_for_each_entry_safe(p, next_p, &w->sinks, list_source) {
1558
list_del(&p->list_sink);
1559
list_del(&p->list_source);
1560
list_del(&p->list);
1561
kfree(p->long_name);
1562
kfree(p);
1563
}
1564
kfree(w->kcontrols);
1565
kfree(w->name);
1566
kfree(w);
1567
}
1568
}
1569
1570
static struct snd_soc_dapm_widget *dapm_find_widget(
1571
struct snd_soc_dapm_context *dapm, const char *pin,
1572
bool search_other_contexts)
1573
{
1574
struct snd_soc_dapm_widget *w;
1575
struct snd_soc_dapm_widget *fallback = NULL;
1576
1577
list_for_each_entry(w, &dapm->card->widgets, list) {
1578
if (!strcmp(w->name, pin)) {
1579
if (w->dapm == dapm)
1580
return w;
1581
else
1582
fallback = w;
1583
}
1584
}
1585
1586
if (search_other_contexts)
1587
return fallback;
1588
1589
return NULL;
1590
}
1591
1592
static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
1593
const char *pin, int status)
1594
{
1595
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
1596
1597
if (!w) {
1598
dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
1599
return -EINVAL;
1600
}
1601
1602
w->connected = status;
1603
if (status == 0)
1604
w->force = 0;
1605
1606
return 0;
1607
}
1608
1609
/**
1610
* snd_soc_dapm_sync - scan and power dapm paths
1611
* @dapm: DAPM context
1612
*
1613
* Walks all dapm audio paths and powers widgets according to their
1614
* stream or path usage.
1615
*
1616
* Returns 0 for success.
1617
*/
1618
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
1619
{
1620
return dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
1621
}
1622
EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
1623
1624
static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
1625
const struct snd_soc_dapm_route *route)
1626
{
1627
struct snd_soc_dapm_path *path;
1628
struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
1629
struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
1630
const char *sink;
1631
const char *control = route->control;
1632
const char *source;
1633
char prefixed_sink[80];
1634
char prefixed_source[80];
1635
int ret = 0;
1636
1637
if (dapm->codec && dapm->codec->name_prefix) {
1638
snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
1639
dapm->codec->name_prefix, route->sink);
1640
sink = prefixed_sink;
1641
snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
1642
dapm->codec->name_prefix, route->source);
1643
source = prefixed_source;
1644
} else {
1645
sink = route->sink;
1646
source = route->source;
1647
}
1648
1649
/*
1650
* find src and dest widgets over all widgets but favor a widget from
1651
* current DAPM context
1652
*/
1653
list_for_each_entry(w, &dapm->card->widgets, list) {
1654
if (!wsink && !(strcmp(w->name, sink))) {
1655
wtsink = w;
1656
if (w->dapm == dapm)
1657
wsink = w;
1658
continue;
1659
}
1660
if (!wsource && !(strcmp(w->name, source))) {
1661
wtsource = w;
1662
if (w->dapm == dapm)
1663
wsource = w;
1664
}
1665
}
1666
/* use widget from another DAPM context if not found from this */
1667
if (!wsink)
1668
wsink = wtsink;
1669
if (!wsource)
1670
wsource = wtsource;
1671
1672
if (wsource == NULL || wsink == NULL)
1673
return -ENODEV;
1674
1675
path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
1676
if (!path)
1677
return -ENOMEM;
1678
1679
path->source = wsource;
1680
path->sink = wsink;
1681
path->connected = route->connected;
1682
INIT_LIST_HEAD(&path->list);
1683
INIT_LIST_HEAD(&path->list_source);
1684
INIT_LIST_HEAD(&path->list_sink);
1685
1686
/* check for external widgets */
1687
if (wsink->id == snd_soc_dapm_input) {
1688
if (wsource->id == snd_soc_dapm_micbias ||
1689
wsource->id == snd_soc_dapm_mic ||
1690
wsource->id == snd_soc_dapm_line ||
1691
wsource->id == snd_soc_dapm_output)
1692
wsink->ext = 1;
1693
}
1694
if (wsource->id == snd_soc_dapm_output) {
1695
if (wsink->id == snd_soc_dapm_spk ||
1696
wsink->id == snd_soc_dapm_hp ||
1697
wsink->id == snd_soc_dapm_line ||
1698
wsink->id == snd_soc_dapm_input)
1699
wsource->ext = 1;
1700
}
1701
1702
/* connect static paths */
1703
if (control == NULL) {
1704
list_add(&path->list, &dapm->card->paths);
1705
list_add(&path->list_sink, &wsink->sources);
1706
list_add(&path->list_source, &wsource->sinks);
1707
path->connect = 1;
1708
return 0;
1709
}
1710
1711
/* connect dynamic paths */
1712
switch (wsink->id) {
1713
case snd_soc_dapm_adc:
1714
case snd_soc_dapm_dac:
1715
case snd_soc_dapm_pga:
1716
case snd_soc_dapm_out_drv:
1717
case snd_soc_dapm_input:
1718
case snd_soc_dapm_output:
1719
case snd_soc_dapm_micbias:
1720
case snd_soc_dapm_vmid:
1721
case snd_soc_dapm_pre:
1722
case snd_soc_dapm_post:
1723
case snd_soc_dapm_supply:
1724
case snd_soc_dapm_aif_in:
1725
case snd_soc_dapm_aif_out:
1726
list_add(&path->list, &dapm->card->paths);
1727
list_add(&path->list_sink, &wsink->sources);
1728
list_add(&path->list_source, &wsource->sinks);
1729
path->connect = 1;
1730
return 0;
1731
case snd_soc_dapm_mux:
1732
case snd_soc_dapm_virt_mux:
1733
case snd_soc_dapm_value_mux:
1734
ret = dapm_connect_mux(dapm, wsource, wsink, path, control,
1735
&wsink->kcontrol_news[0]);
1736
if (ret != 0)
1737
goto err;
1738
break;
1739
case snd_soc_dapm_switch:
1740
case snd_soc_dapm_mixer:
1741
case snd_soc_dapm_mixer_named_ctl:
1742
ret = dapm_connect_mixer(dapm, wsource, wsink, path, control);
1743
if (ret != 0)
1744
goto err;
1745
break;
1746
case snd_soc_dapm_hp:
1747
case snd_soc_dapm_mic:
1748
case snd_soc_dapm_line:
1749
case snd_soc_dapm_spk:
1750
list_add(&path->list, &dapm->card->paths);
1751
list_add(&path->list_sink, &wsink->sources);
1752
list_add(&path->list_source, &wsource->sinks);
1753
path->connect = 0;
1754
return 0;
1755
}
1756
return 0;
1757
1758
err:
1759
dev_warn(dapm->dev, "asoc: no dapm match for %s --> %s --> %s\n",
1760
source, control, sink);
1761
kfree(path);
1762
return ret;
1763
}
1764
1765
/**
1766
* snd_soc_dapm_add_routes - Add routes between DAPM widgets
1767
* @dapm: DAPM context
1768
* @route: audio routes
1769
* @num: number of routes
1770
*
1771
* Connects 2 dapm widgets together via a named audio path. The sink is
1772
* the widget receiving the audio signal, whilst the source is the sender
1773
* of the audio signal.
1774
*
1775
* Returns 0 for success else error. On error all resources can be freed
1776
* with a call to snd_soc_card_free().
1777
*/
1778
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
1779
const struct snd_soc_dapm_route *route, int num)
1780
{
1781
int i, ret;
1782
1783
for (i = 0; i < num; i++) {
1784
ret = snd_soc_dapm_add_route(dapm, route);
1785
if (ret < 0) {
1786
dev_err(dapm->dev, "Failed to add route %s->%s\n",
1787
route->source, route->sink);
1788
return ret;
1789
}
1790
route++;
1791
}
1792
1793
return 0;
1794
}
1795
EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
1796
1797
/**
1798
* snd_soc_dapm_new_widgets - add new dapm widgets
1799
* @dapm: DAPM context
1800
*
1801
* Checks the codec for any new dapm widgets and creates them if found.
1802
*
1803
* Returns 0 for success.
1804
*/
1805
int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
1806
{
1807
struct snd_soc_dapm_widget *w;
1808
unsigned int val;
1809
1810
list_for_each_entry(w, &dapm->card->widgets, list)
1811
{
1812
if (w->new)
1813
continue;
1814
1815
if (w->num_kcontrols) {
1816
w->kcontrols = kzalloc(w->num_kcontrols *
1817
sizeof(struct snd_kcontrol *),
1818
GFP_KERNEL);
1819
if (!w->kcontrols)
1820
return -ENOMEM;
1821
}
1822
1823
switch(w->id) {
1824
case snd_soc_dapm_switch:
1825
case snd_soc_dapm_mixer:
1826
case snd_soc_dapm_mixer_named_ctl:
1827
w->power_check = dapm_generic_check_power;
1828
dapm_new_mixer(w);
1829
break;
1830
case snd_soc_dapm_mux:
1831
case snd_soc_dapm_virt_mux:
1832
case snd_soc_dapm_value_mux:
1833
w->power_check = dapm_generic_check_power;
1834
dapm_new_mux(w);
1835
break;
1836
case snd_soc_dapm_adc:
1837
case snd_soc_dapm_aif_out:
1838
w->power_check = dapm_adc_check_power;
1839
break;
1840
case snd_soc_dapm_dac:
1841
case snd_soc_dapm_aif_in:
1842
w->power_check = dapm_dac_check_power;
1843
break;
1844
case snd_soc_dapm_pga:
1845
case snd_soc_dapm_out_drv:
1846
w->power_check = dapm_generic_check_power;
1847
dapm_new_pga(w);
1848
break;
1849
case snd_soc_dapm_input:
1850
case snd_soc_dapm_output:
1851
case snd_soc_dapm_micbias:
1852
case snd_soc_dapm_spk:
1853
case snd_soc_dapm_hp:
1854
case snd_soc_dapm_mic:
1855
case snd_soc_dapm_line:
1856
w->power_check = dapm_generic_check_power;
1857
break;
1858
case snd_soc_dapm_supply:
1859
w->power_check = dapm_supply_check_power;
1860
case snd_soc_dapm_vmid:
1861
case snd_soc_dapm_pre:
1862
case snd_soc_dapm_post:
1863
break;
1864
}
1865
1866
/* Read the initial power state from the device */
1867
if (w->reg >= 0) {
1868
val = snd_soc_read(w->codec, w->reg);
1869
val &= 1 << w->shift;
1870
if (w->invert)
1871
val = !val;
1872
1873
if (val)
1874
w->power = 1;
1875
}
1876
1877
w->new = 1;
1878
1879
dapm_debugfs_add_widget(w);
1880
}
1881
1882
dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
1883
return 0;
1884
}
1885
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
1886
1887
/**
1888
* snd_soc_dapm_get_volsw - dapm mixer get callback
1889
* @kcontrol: mixer control
1890
* @ucontrol: control element information
1891
*
1892
* Callback to get the value of a dapm mixer control.
1893
*
1894
* Returns 0 for success.
1895
*/
1896
int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
1897
struct snd_ctl_elem_value *ucontrol)
1898
{
1899
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1900
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1901
struct soc_mixer_control *mc =
1902
(struct soc_mixer_control *)kcontrol->private_value;
1903
unsigned int reg = mc->reg;
1904
unsigned int shift = mc->shift;
1905
unsigned int rshift = mc->rshift;
1906
int max = mc->max;
1907
unsigned int invert = mc->invert;
1908
unsigned int mask = (1 << fls(max)) - 1;
1909
1910
ucontrol->value.integer.value[0] =
1911
(snd_soc_read(widget->codec, reg) >> shift) & mask;
1912
if (shift != rshift)
1913
ucontrol->value.integer.value[1] =
1914
(snd_soc_read(widget->codec, reg) >> rshift) & mask;
1915
if (invert) {
1916
ucontrol->value.integer.value[0] =
1917
max - ucontrol->value.integer.value[0];
1918
if (shift != rshift)
1919
ucontrol->value.integer.value[1] =
1920
max - ucontrol->value.integer.value[1];
1921
}
1922
1923
return 0;
1924
}
1925
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
1926
1927
/**
1928
* snd_soc_dapm_put_volsw - dapm mixer set callback
1929
* @kcontrol: mixer control
1930
* @ucontrol: control element information
1931
*
1932
* Callback to set the value of a dapm mixer control.
1933
*
1934
* Returns 0 for success.
1935
*/
1936
int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1937
struct snd_ctl_elem_value *ucontrol)
1938
{
1939
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1940
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1941
struct snd_soc_codec *codec = widget->codec;
1942
struct soc_mixer_control *mc =
1943
(struct soc_mixer_control *)kcontrol->private_value;
1944
unsigned int reg = mc->reg;
1945
unsigned int shift = mc->shift;
1946
int max = mc->max;
1947
unsigned int mask = (1 << fls(max)) - 1;
1948
unsigned int invert = mc->invert;
1949
unsigned int val;
1950
int connect, change;
1951
struct snd_soc_dapm_update update;
1952
int wi;
1953
1954
val = (ucontrol->value.integer.value[0] & mask);
1955
1956
if (invert)
1957
val = max - val;
1958
mask = mask << shift;
1959
val = val << shift;
1960
1961
if (val)
1962
/* new connection */
1963
connect = invert ? 0 : 1;
1964
else
1965
/* old connection must be powered down */
1966
connect = invert ? 1 : 0;
1967
1968
mutex_lock(&codec->mutex);
1969
1970
change = snd_soc_test_bits(widget->codec, reg, mask, val);
1971
if (change) {
1972
for (wi = 0; wi < wlist->num_widgets; wi++) {
1973
widget = wlist->widgets[wi];
1974
1975
widget->value = val;
1976
1977
update.kcontrol = kcontrol;
1978
update.widget = widget;
1979
update.reg = reg;
1980
update.mask = mask;
1981
update.val = val;
1982
widget->dapm->update = &update;
1983
1984
dapm_mixer_update_power(widget, kcontrol, connect);
1985
1986
widget->dapm->update = NULL;
1987
}
1988
}
1989
1990
mutex_unlock(&codec->mutex);
1991
return 0;
1992
}
1993
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
1994
1995
/**
1996
* snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
1997
* @kcontrol: mixer control
1998
* @ucontrol: control element information
1999
*
2000
* Callback to get the value of a dapm enumerated double mixer control.
2001
*
2002
* Returns 0 for success.
2003
*/
2004
int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
2005
struct snd_ctl_elem_value *ucontrol)
2006
{
2007
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2008
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2009
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2010
unsigned int val, bitmask;
2011
2012
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
2013
;
2014
val = snd_soc_read(widget->codec, e->reg);
2015
ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
2016
if (e->shift_l != e->shift_r)
2017
ucontrol->value.enumerated.item[1] =
2018
(val >> e->shift_r) & (bitmask - 1);
2019
2020
return 0;
2021
}
2022
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
2023
2024
/**
2025
* snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
2026
* @kcontrol: mixer control
2027
* @ucontrol: control element information
2028
*
2029
* Callback to set the value of a dapm enumerated double mixer control.
2030
*
2031
* Returns 0 for success.
2032
*/
2033
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2034
struct snd_ctl_elem_value *ucontrol)
2035
{
2036
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2037
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2038
struct snd_soc_codec *codec = widget->codec;
2039
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2040
unsigned int val, mux, change;
2041
unsigned int mask, bitmask;
2042
struct snd_soc_dapm_update update;
2043
int wi;
2044
2045
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
2046
;
2047
if (ucontrol->value.enumerated.item[0] > e->max - 1)
2048
return -EINVAL;
2049
mux = ucontrol->value.enumerated.item[0];
2050
val = mux << e->shift_l;
2051
mask = (bitmask - 1) << e->shift_l;
2052
if (e->shift_l != e->shift_r) {
2053
if (ucontrol->value.enumerated.item[1] > e->max - 1)
2054
return -EINVAL;
2055
val |= ucontrol->value.enumerated.item[1] << e->shift_r;
2056
mask |= (bitmask - 1) << e->shift_r;
2057
}
2058
2059
mutex_lock(&codec->mutex);
2060
2061
change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
2062
if (change) {
2063
for (wi = 0; wi < wlist->num_widgets; wi++) {
2064
widget = wlist->widgets[wi];
2065
2066
widget->value = val;
2067
2068
update.kcontrol = kcontrol;
2069
update.widget = widget;
2070
update.reg = e->reg;
2071
update.mask = mask;
2072
update.val = val;
2073
widget->dapm->update = &update;
2074
2075
dapm_mux_update_power(widget, kcontrol, change, mux, e);
2076
2077
widget->dapm->update = NULL;
2078
}
2079
}
2080
2081
mutex_unlock(&codec->mutex);
2082
return change;
2083
}
2084
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
2085
2086
/**
2087
* snd_soc_dapm_get_enum_virt - Get virtual DAPM mux
2088
* @kcontrol: mixer control
2089
* @ucontrol: control element information
2090
*
2091
* Returns 0 for success.
2092
*/
2093
int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
2094
struct snd_ctl_elem_value *ucontrol)
2095
{
2096
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2097
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2098
2099
ucontrol->value.enumerated.item[0] = widget->value;
2100
2101
return 0;
2102
}
2103
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
2104
2105
/**
2106
* snd_soc_dapm_put_enum_virt - Set virtual DAPM mux
2107
* @kcontrol: mixer control
2108
* @ucontrol: control element information
2109
*
2110
* Returns 0 for success.
2111
*/
2112
int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
2113
struct snd_ctl_elem_value *ucontrol)
2114
{
2115
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2116
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2117
struct snd_soc_codec *codec = widget->codec;
2118
struct soc_enum *e =
2119
(struct soc_enum *)kcontrol->private_value;
2120
int change;
2121
int ret = 0;
2122
int wi;
2123
2124
if (ucontrol->value.enumerated.item[0] >= e->max)
2125
return -EINVAL;
2126
2127
mutex_lock(&codec->mutex);
2128
2129
change = widget->value != ucontrol->value.enumerated.item[0];
2130
if (change) {
2131
for (wi = 0; wi < wlist->num_widgets; wi++) {
2132
widget = wlist->widgets[wi];
2133
2134
widget->value = ucontrol->value.enumerated.item[0];
2135
2136
dapm_mux_update_power(widget, kcontrol, change,
2137
widget->value, e);
2138
}
2139
}
2140
2141
mutex_unlock(&codec->mutex);
2142
return ret;
2143
}
2144
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
2145
2146
/**
2147
* snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get
2148
* callback
2149
* @kcontrol: mixer control
2150
* @ucontrol: control element information
2151
*
2152
* Callback to get the value of a dapm semi enumerated double mixer control.
2153
*
2154
* Semi enumerated mixer: the enumerated items are referred as values. Can be
2155
* used for handling bitfield coded enumeration for example.
2156
*
2157
* Returns 0 for success.
2158
*/
2159
int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
2160
struct snd_ctl_elem_value *ucontrol)
2161
{
2162
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2163
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2164
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2165
unsigned int reg_val, val, mux;
2166
2167
reg_val = snd_soc_read(widget->codec, e->reg);
2168
val = (reg_val >> e->shift_l) & e->mask;
2169
for (mux = 0; mux < e->max; mux++) {
2170
if (val == e->values[mux])
2171
break;
2172
}
2173
ucontrol->value.enumerated.item[0] = mux;
2174
if (e->shift_l != e->shift_r) {
2175
val = (reg_val >> e->shift_r) & e->mask;
2176
for (mux = 0; mux < e->max; mux++) {
2177
if (val == e->values[mux])
2178
break;
2179
}
2180
ucontrol->value.enumerated.item[1] = mux;
2181
}
2182
2183
return 0;
2184
}
2185
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double);
2186
2187
/**
2188
* snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set
2189
* callback
2190
* @kcontrol: mixer control
2191
* @ucontrol: control element information
2192
*
2193
* Callback to set the value of a dapm semi enumerated double mixer control.
2194
*
2195
* Semi enumerated mixer: the enumerated items are referred as values. Can be
2196
* used for handling bitfield coded enumeration for example.
2197
*
2198
* Returns 0 for success.
2199
*/
2200
int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
2201
struct snd_ctl_elem_value *ucontrol)
2202
{
2203
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2204
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2205
struct snd_soc_codec *codec = widget->codec;
2206
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2207
unsigned int val, mux, change;
2208
unsigned int mask;
2209
struct snd_soc_dapm_update update;
2210
int wi;
2211
2212
if (ucontrol->value.enumerated.item[0] > e->max - 1)
2213
return -EINVAL;
2214
mux = ucontrol->value.enumerated.item[0];
2215
val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l;
2216
mask = e->mask << e->shift_l;
2217
if (e->shift_l != e->shift_r) {
2218
if (ucontrol->value.enumerated.item[1] > e->max - 1)
2219
return -EINVAL;
2220
val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r;
2221
mask |= e->mask << e->shift_r;
2222
}
2223
2224
mutex_lock(&codec->mutex);
2225
2226
change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
2227
if (change) {
2228
for (wi = 0; wi < wlist->num_widgets; wi++) {
2229
widget = wlist->widgets[wi];
2230
2231
widget->value = val;
2232
2233
update.kcontrol = kcontrol;
2234
update.widget = widget;
2235
update.reg = e->reg;
2236
update.mask = mask;
2237
update.val = val;
2238
widget->dapm->update = &update;
2239
2240
dapm_mux_update_power(widget, kcontrol, change, mux, e);
2241
2242
widget->dapm->update = NULL;
2243
}
2244
}
2245
2246
mutex_unlock(&codec->mutex);
2247
return change;
2248
}
2249
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
2250
2251
/**
2252
* snd_soc_dapm_info_pin_switch - Info for a pin switch
2253
*
2254
* @kcontrol: mixer control
2255
* @uinfo: control element information
2256
*
2257
* Callback to provide information about a pin switch control.
2258
*/
2259
int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
2260
struct snd_ctl_elem_info *uinfo)
2261
{
2262
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2263
uinfo->count = 1;
2264
uinfo->value.integer.min = 0;
2265
uinfo->value.integer.max = 1;
2266
2267
return 0;
2268
}
2269
EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
2270
2271
/**
2272
* snd_soc_dapm_get_pin_switch - Get information for a pin switch
2273
*
2274
* @kcontrol: mixer control
2275
* @ucontrol: Value
2276
*/
2277
int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
2278
struct snd_ctl_elem_value *ucontrol)
2279
{
2280
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2281
const char *pin = (const char *)kcontrol->private_value;
2282
2283
mutex_lock(&codec->mutex);
2284
2285
ucontrol->value.integer.value[0] =
2286
snd_soc_dapm_get_pin_status(&codec->dapm, pin);
2287
2288
mutex_unlock(&codec->mutex);
2289
2290
return 0;
2291
}
2292
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
2293
2294
/**
2295
* snd_soc_dapm_put_pin_switch - Set information for a pin switch
2296
*
2297
* @kcontrol: mixer control
2298
* @ucontrol: Value
2299
*/
2300
int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
2301
struct snd_ctl_elem_value *ucontrol)
2302
{
2303
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2304
const char *pin = (const char *)kcontrol->private_value;
2305
2306
mutex_lock(&codec->mutex);
2307
2308
if (ucontrol->value.integer.value[0])
2309
snd_soc_dapm_enable_pin(&codec->dapm, pin);
2310
else
2311
snd_soc_dapm_disable_pin(&codec->dapm, pin);
2312
2313
snd_soc_dapm_sync(&codec->dapm);
2314
2315
mutex_unlock(&codec->mutex);
2316
2317
return 0;
2318
}
2319
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
2320
2321
/**
2322
* snd_soc_dapm_new_control - create new dapm control
2323
* @dapm: DAPM context
2324
* @widget: widget template
2325
*
2326
* Creates a new dapm control based upon the template.
2327
*
2328
* Returns 0 for success else error.
2329
*/
2330
int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2331
const struct snd_soc_dapm_widget *widget)
2332
{
2333
struct snd_soc_dapm_widget *w;
2334
size_t name_len;
2335
2336
if ((w = dapm_cnew_widget(widget)) == NULL)
2337
return -ENOMEM;
2338
2339
name_len = strlen(widget->name) + 1;
2340
if (dapm->codec && dapm->codec->name_prefix)
2341
name_len += 1 + strlen(dapm->codec->name_prefix);
2342
w->name = kmalloc(name_len, GFP_KERNEL);
2343
if (w->name == NULL) {
2344
kfree(w);
2345
return -ENOMEM;
2346
}
2347
if (dapm->codec && dapm->codec->name_prefix)
2348
snprintf(w->name, name_len, "%s %s",
2349
dapm->codec->name_prefix, widget->name);
2350
else
2351
snprintf(w->name, name_len, "%s", widget->name);
2352
2353
dapm->n_widgets++;
2354
w->dapm = dapm;
2355
w->codec = dapm->codec;
2356
INIT_LIST_HEAD(&w->sources);
2357
INIT_LIST_HEAD(&w->sinks);
2358
INIT_LIST_HEAD(&w->list);
2359
list_add(&w->list, &dapm->card->widgets);
2360
2361
/* machine layer set ups unconnected pins and insertions */
2362
w->connected = 1;
2363
return 0;
2364
}
2365
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
2366
2367
/**
2368
* snd_soc_dapm_new_controls - create new dapm controls
2369
* @dapm: DAPM context
2370
* @widget: widget array
2371
* @num: number of widgets
2372
*
2373
* Creates new DAPM controls based upon the templates.
2374
*
2375
* Returns 0 for success else error.
2376
*/
2377
int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
2378
const struct snd_soc_dapm_widget *widget,
2379
int num)
2380
{
2381
int i, ret;
2382
2383
for (i = 0; i < num; i++) {
2384
ret = snd_soc_dapm_new_control(dapm, widget);
2385
if (ret < 0) {
2386
dev_err(dapm->dev,
2387
"ASoC: Failed to create DAPM control %s: %d\n",
2388
widget->name, ret);
2389
return ret;
2390
}
2391
widget++;
2392
}
2393
return 0;
2394
}
2395
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
2396
2397
static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
2398
const char *stream, int event)
2399
{
2400
struct snd_soc_dapm_widget *w;
2401
2402
list_for_each_entry(w, &dapm->card->widgets, list)
2403
{
2404
if (!w->sname || w->dapm != dapm)
2405
continue;
2406
dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
2407
w->name, w->sname, stream, event);
2408
if (strstr(w->sname, stream)) {
2409
switch(event) {
2410
case SND_SOC_DAPM_STREAM_START:
2411
w->active = 1;
2412
break;
2413
case SND_SOC_DAPM_STREAM_STOP:
2414
w->active = 0;
2415
break;
2416
case SND_SOC_DAPM_STREAM_SUSPEND:
2417
case SND_SOC_DAPM_STREAM_RESUME:
2418
case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
2419
case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
2420
break;
2421
}
2422
}
2423
}
2424
2425
dapm_power_widgets(dapm, event);
2426
}
2427
2428
/**
2429
* snd_soc_dapm_stream_event - send a stream event to the dapm core
2430
* @rtd: PCM runtime data
2431
* @stream: stream name
2432
* @event: stream event
2433
*
2434
* Sends a stream event to the dapm core. The core then makes any
2435
* necessary widget power changes.
2436
*
2437
* Returns 0 for success else error.
2438
*/
2439
int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
2440
const char *stream, int event)
2441
{
2442
struct snd_soc_codec *codec = rtd->codec;
2443
2444
if (stream == NULL)
2445
return 0;
2446
2447
mutex_lock(&codec->mutex);
2448
soc_dapm_stream_event(&codec->dapm, stream, event);
2449
mutex_unlock(&codec->mutex);
2450
return 0;
2451
}
2452
2453
/**
2454
* snd_soc_dapm_enable_pin - enable pin.
2455
* @dapm: DAPM context
2456
* @pin: pin name
2457
*
2458
* Enables input/output pin and its parents or children widgets iff there is
2459
* a valid audio route and active audio stream.
2460
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
2461
* do any widget power switching.
2462
*/
2463
int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
2464
{
2465
return snd_soc_dapm_set_pin(dapm, pin, 1);
2466
}
2467
EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
2468
2469
/**
2470
* snd_soc_dapm_force_enable_pin - force a pin to be enabled
2471
* @dapm: DAPM context
2472
* @pin: pin name
2473
*
2474
* Enables input/output pin regardless of any other state. This is
2475
* intended for use with microphone bias supplies used in microphone
2476
* jack detection.
2477
*
2478
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
2479
* do any widget power switching.
2480
*/
2481
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
2482
const char *pin)
2483
{
2484
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
2485
2486
if (!w) {
2487
dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
2488
return -EINVAL;
2489
}
2490
2491
dev_dbg(w->dapm->dev, "dapm: force enable pin %s\n", pin);
2492
w->connected = 1;
2493
w->force = 1;
2494
2495
return 0;
2496
}
2497
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
2498
2499
/**
2500
* snd_soc_dapm_disable_pin - disable pin.
2501
* @dapm: DAPM context
2502
* @pin: pin name
2503
*
2504
* Disables input/output pin and its parents or children widgets.
2505
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
2506
* do any widget power switching.
2507
*/
2508
int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
2509
const char *pin)
2510
{
2511
return snd_soc_dapm_set_pin(dapm, pin, 0);
2512
}
2513
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
2514
2515
/**
2516
* snd_soc_dapm_nc_pin - permanently disable pin.
2517
* @dapm: DAPM context
2518
* @pin: pin name
2519
*
2520
* Marks the specified pin as being not connected, disabling it along
2521
* any parent or child widgets. At present this is identical to
2522
* snd_soc_dapm_disable_pin() but in future it will be extended to do
2523
* additional things such as disabling controls which only affect
2524
* paths through the pin.
2525
*
2526
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
2527
* do any widget power switching.
2528
*/
2529
int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
2530
{
2531
return snd_soc_dapm_set_pin(dapm, pin, 0);
2532
}
2533
EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
2534
2535
/**
2536
* snd_soc_dapm_get_pin_status - get audio pin status
2537
* @dapm: DAPM context
2538
* @pin: audio signal pin endpoint (or start point)
2539
*
2540
* Get audio pin status - connected or disconnected.
2541
*
2542
* Returns 1 for connected otherwise 0.
2543
*/
2544
int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
2545
const char *pin)
2546
{
2547
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
2548
2549
if (w)
2550
return w->connected;
2551
2552
return 0;
2553
}
2554
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
2555
2556
/**
2557
* snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint
2558
* @dapm: DAPM context
2559
* @pin: audio signal pin endpoint (or start point)
2560
*
2561
* Mark the given endpoint or pin as ignoring suspend. When the
2562
* system is disabled a path between two endpoints flagged as ignoring
2563
* suspend will not be disabled. The path must already be enabled via
2564
* normal means at suspend time, it will not be turned on if it was not
2565
* already enabled.
2566
*/
2567
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
2568
const char *pin)
2569
{
2570
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, false);
2571
2572
if (!w) {
2573
dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
2574
return -EINVAL;
2575
}
2576
2577
w->ignore_suspend = 1;
2578
2579
return 0;
2580
}
2581
EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
2582
2583
/**
2584
* snd_soc_dapm_free - free dapm resources
2585
* @card: SoC device
2586
*
2587
* Free all dapm widgets and resources.
2588
*/
2589
void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm)
2590
{
2591
snd_soc_dapm_sys_remove(dapm->dev);
2592
dapm_debugfs_cleanup(dapm);
2593
dapm_free_widgets(dapm);
2594
list_del(&dapm->list);
2595
}
2596
EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
2597
2598
static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
2599
{
2600
struct snd_soc_dapm_widget *w;
2601
LIST_HEAD(down_list);
2602
int powerdown = 0;
2603
2604
list_for_each_entry(w, &dapm->card->widgets, list) {
2605
if (w->dapm != dapm)
2606
continue;
2607
if (w->power) {
2608
dapm_seq_insert(w, &down_list, false);
2609
w->power = 0;
2610
powerdown = 1;
2611
}
2612
}
2613
2614
/* If there were no widgets to power down we're already in
2615
* standby.
2616
*/
2617
if (powerdown) {
2618
snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_PREPARE);
2619
dapm_seq_run(dapm, &down_list, 0, false);
2620
snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_STANDBY);
2621
}
2622
}
2623
2624
/*
2625
* snd_soc_dapm_shutdown - callback for system shutdown
2626
*/
2627
void snd_soc_dapm_shutdown(struct snd_soc_card *card)
2628
{
2629
struct snd_soc_codec *codec;
2630
2631
list_for_each_entry(codec, &card->codec_dev_list, list) {
2632
soc_dapm_shutdown_codec(&codec->dapm);
2633
snd_soc_dapm_set_bias_level(&codec->dapm, SND_SOC_BIAS_OFF);
2634
}
2635
}
2636
2637
/* Module information */
2638
MODULE_AUTHOR("Liam Girdwood, [email protected]");
2639
MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
2640
MODULE_LICENSE("GPL");
2641
2642