aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2012-04-08 15:48:52 -0400
committerJiri Kosina <jkosina@suse.cz>2012-04-08 15:48:52 -0400
commite75d660672ddd11704b7f0fdb8ff21968587b266 (patch)
treeccb9c107744c10b553c0373e450bee3971d16c00 /sound/soc/soc-dapm.c
parent61282f37927143e45b03153f3e7b48d6b702147a (diff)
parent0034102808e0dbbf3a2394b82b1bb40b5778de9e (diff)
Merge branch 'master' into for-next
Merge with latest Linus' tree, as I have incoming patches that fix code that is newer than current HEAD of for-next. Conflicts: drivers/net/ethernet/realtek/r8169.c
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c428
1 files changed, 296 insertions, 132 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1f55ded4047f..5cbd2d7623b8 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -14,19 +14,13 @@
14 * dynamic configuration of codec internal audio paths and active 14 * dynamic configuration of codec internal audio paths and active
15 * DACs/ADCs. 15 * DACs/ADCs.
16 * o Platform power domain - can support external components i.e. amps and 16 * o Platform power domain - can support external components i.e. amps and
17 * mic/meadphone insertion events. 17 * mic/headphone insertion events.
18 * o Automatic Mic Bias support 18 * o Automatic Mic Bias support
19 * o Jack insertion power event initiation - e.g. hp insertion will enable 19 * o Jack insertion power event initiation - e.g. hp insertion will enable
20 * sinks, dacs, etc 20 * sinks, dacs, etc
21 * o Delayed powerdown of audio susbsystem to reduce pops between a quick 21 * o Delayed power down of audio subsystem to reduce pops between a quick
22 * device reopen. 22 * device reopen.
23 * 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 */ 24 */
31 25
32#include <linux/module.h> 26#include <linux/module.h>
@@ -40,6 +34,7 @@
40#include <linux/jiffies.h> 34#include <linux/jiffies.h>
41#include <linux/debugfs.h> 35#include <linux/debugfs.h>
42#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
37#include <linux/regulator/consumer.h>
43#include <linux/slab.h> 38#include <linux/slab.h>
44#include <sound/core.h> 39#include <sound/core.h>
45#include <sound/pcm.h> 40#include <sound/pcm.h>
@@ -55,7 +50,9 @@
55static int dapm_up_seq[] = { 50static int dapm_up_seq[] = {
56 [snd_soc_dapm_pre] = 0, 51 [snd_soc_dapm_pre] = 0,
57 [snd_soc_dapm_supply] = 1, 52 [snd_soc_dapm_supply] = 1,
53 [snd_soc_dapm_regulator_supply] = 1,
58 [snd_soc_dapm_micbias] = 2, 54 [snd_soc_dapm_micbias] = 2,
55 [snd_soc_dapm_dai] = 3,
59 [snd_soc_dapm_aif_in] = 3, 56 [snd_soc_dapm_aif_in] = 3,
60 [snd_soc_dapm_aif_out] = 3, 57 [snd_soc_dapm_aif_out] = 3,
61 [snd_soc_dapm_mic] = 4, 58 [snd_soc_dapm_mic] = 4,
@@ -90,6 +87,8 @@ static int dapm_down_seq[] = {
90 [snd_soc_dapm_value_mux] = 9, 87 [snd_soc_dapm_value_mux] = 9,
91 [snd_soc_dapm_aif_in] = 10, 88 [snd_soc_dapm_aif_in] = 10,
92 [snd_soc_dapm_aif_out] = 10, 89 [snd_soc_dapm_aif_out] = 10,
90 [snd_soc_dapm_dai] = 10,
91 [snd_soc_dapm_regulator_supply] = 11,
93 [snd_soc_dapm_supply] = 11, 92 [snd_soc_dapm_supply] = 11,
94 [snd_soc_dapm_post] = 12, 93 [snd_soc_dapm_post] = 12,
95}; 94};
@@ -172,6 +171,19 @@ static inline struct snd_soc_card *dapm_get_soc_card(
172 return NULL; 171 return NULL;
173} 172}
174 173
174static void dapm_reset(struct snd_soc_card *card)
175{
176 struct snd_soc_dapm_widget *w;
177
178 memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
179
180 list_for_each_entry(w, &card->widgets, list) {
181 w->power_checked = false;
182 w->inputs = -1;
183 w->outputs = -1;
184 }
185}
186
175static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg) 187static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
176{ 188{
177 if (w->codec) 189 if (w->codec)
@@ -197,21 +209,28 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
197static int soc_widget_update_bits(struct snd_soc_dapm_widget *w, 209static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
198 unsigned short reg, unsigned int mask, unsigned int value) 210 unsigned short reg, unsigned int mask, unsigned int value)
199{ 211{
200 int change; 212 bool change;
201 unsigned int old, new; 213 unsigned int old, new;
202 int ret; 214 int ret;
203 215
204 ret = soc_widget_read(w, reg); 216 if (w->codec && w->codec->using_regmap) {
205 if (ret < 0) 217 ret = regmap_update_bits_check(w->codec->control_data,
206 return ret; 218 reg, mask, value, &change);
207 219 if (ret != 0)
208 old = ret; 220 return ret;
209 new = (old & ~mask) | (value & mask); 221 } else {
210 change = old != new; 222 ret = soc_widget_read(w, reg);
211 if (change) {
212 ret = soc_widget_write(w, reg, new);
213 if (ret < 0) 223 if (ret < 0)
214 return ret; 224 return ret;
225
226 old = ret;
227 new = (old & ~mask) | (value & mask);
228 change = old != new;
229 if (change) {
230 ret = soc_widget_write(w, reg, new);
231 if (ret < 0)
232 return ret;
233 }
215 } 234 }
216 235
217 return change; 236 return change;
@@ -345,8 +364,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
345 case snd_soc_dapm_micbias: 364 case snd_soc_dapm_micbias:
346 case snd_soc_dapm_vmid: 365 case snd_soc_dapm_vmid:
347 case snd_soc_dapm_supply: 366 case snd_soc_dapm_supply:
367 case snd_soc_dapm_regulator_supply:
348 case snd_soc_dapm_aif_in: 368 case snd_soc_dapm_aif_in:
349 case snd_soc_dapm_aif_out: 369 case snd_soc_dapm_aif_out:
370 case snd_soc_dapm_dai:
350 case snd_soc_dapm_hp: 371 case snd_soc_dapm_hp:
351 case snd_soc_dapm_mic: 372 case snd_soc_dapm_mic:
352 case snd_soc_dapm_spk: 373 case snd_soc_dapm_spk:
@@ -504,17 +525,17 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
504 * for widgets so cut the prefix off 525 * for widgets so cut the prefix off
505 * the front of the widget name. 526 * the front of the widget name.
506 */ 527 */
507 snprintf(path->long_name, name_len, "%s %s", 528 snprintf((char *)path->long_name, name_len,
508 w->name + prefix_len, 529 "%s %s", w->name + prefix_len,
509 w->kcontrol_news[i].name); 530 w->kcontrol_news[i].name);
510 break; 531 break;
511 case snd_soc_dapm_mixer_named_ctl: 532 case snd_soc_dapm_mixer_named_ctl:
512 snprintf(path->long_name, name_len, "%s", 533 snprintf((char *)path->long_name, name_len,
513 w->kcontrol_news[i].name); 534 "%s", w->kcontrol_news[i].name);
514 break; 535 break;
515 } 536 }
516 537
517 path->long_name[name_len - 1] = '\0'; 538 ((char *)path->long_name)[name_len - 1] = '\0';
518 539
519 path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i], 540 path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
520 wlist, path->long_name, 541 wlist, path->long_name,
@@ -548,7 +569,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
548 struct snd_soc_dapm_widget_list *wlist; 569 struct snd_soc_dapm_widget_list *wlist;
549 int shared, wlistentries; 570 int shared, wlistentries;
550 size_t wlistsize; 571 size_t wlistsize;
551 char *name; 572 const char *name;
552 573
553 if (w->num_kcontrols != 1) { 574 if (w->num_kcontrols != 1) {
554 dev_err(dapm->dev, 575 dev_err(dapm->dev,
@@ -673,12 +694,18 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
673 694
674 DAPM_UPDATE_STAT(widget, path_checks); 695 DAPM_UPDATE_STAT(widget, path_checks);
675 696
676 if (widget->id == snd_soc_dapm_supply) 697 switch (widget->id) {
698 case snd_soc_dapm_supply:
699 case snd_soc_dapm_regulator_supply:
677 return 0; 700 return 0;
701 default:
702 break;
703 }
678 704
679 switch (widget->id) { 705 switch (widget->id) {
680 case snd_soc_dapm_adc: 706 case snd_soc_dapm_adc:
681 case snd_soc_dapm_aif_out: 707 case snd_soc_dapm_aif_out:
708 case snd_soc_dapm_dai:
682 if (widget->active) { 709 if (widget->active) {
683 widget->outputs = snd_soc_dapm_suspend_check(widget); 710 widget->outputs = snd_soc_dapm_suspend_check(widget);
684 return widget->outputs; 711 return widget->outputs;
@@ -738,13 +765,19 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
738 765
739 DAPM_UPDATE_STAT(widget, path_checks); 766 DAPM_UPDATE_STAT(widget, path_checks);
740 767
741 if (widget->id == snd_soc_dapm_supply) 768 switch (widget->id) {
769 case snd_soc_dapm_supply:
770 case snd_soc_dapm_regulator_supply:
742 return 0; 771 return 0;
772 default:
773 break;
774 }
743 775
744 /* active stream ? */ 776 /* active stream ? */
745 switch (widget->id) { 777 switch (widget->id) {
746 case snd_soc_dapm_dac: 778 case snd_soc_dapm_dac:
747 case snd_soc_dapm_aif_in: 779 case snd_soc_dapm_aif_in:
780 case snd_soc_dapm_dai:
748 if (widget->active) { 781 if (widget->active) {
749 widget->inputs = snd_soc_dapm_suspend_check(widget); 782 widget->inputs = snd_soc_dapm_suspend_check(widget);
750 return widget->inputs; 783 return widget->inputs;
@@ -821,6 +854,19 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
821} 854}
822EXPORT_SYMBOL_GPL(dapm_reg_event); 855EXPORT_SYMBOL_GPL(dapm_reg_event);
823 856
857/*
858 * Handler for regulator supply widget.
859 */
860int dapm_regulator_event(struct snd_soc_dapm_widget *w,
861 struct snd_kcontrol *kcontrol, int event)
862{
863 if (SND_SOC_DAPM_EVENT_ON(event))
864 return regulator_enable(w->priv);
865 else
866 return regulator_disable_deferred(w->priv, w->shift);
867}
868EXPORT_SYMBOL_GPL(dapm_regulator_event);
869
824static int dapm_widget_power_check(struct snd_soc_dapm_widget *w) 870static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
825{ 871{
826 if (w->power_checked) 872 if (w->power_checked)
@@ -851,6 +897,13 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
851 return out != 0 && in != 0; 897 return out != 0 && in != 0;
852} 898}
853 899
900static int dapm_dai_check_power(struct snd_soc_dapm_widget *w)
901{
902 DAPM_UPDATE_STAT(w, power_checks);
903
904 return w->active;
905}
906
854/* Check to see if an ADC has power */ 907/* Check to see if an ADC has power */
855static int dapm_adc_check_power(struct snd_soc_dapm_widget *w) 908static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
856{ 909{
@@ -1251,7 +1304,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
1251 dev_err(d->dev, "Failed to turn off bias: %d\n", ret); 1304 dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
1252 1305
1253 if (d->dev) 1306 if (d->dev)
1254 pm_runtime_put_sync(d->dev); 1307 pm_runtime_put(d->dev);
1255 } 1308 }
1256 1309
1257 /* If we just powered up then move to active bias */ 1310 /* If we just powered up then move to active bias */
@@ -1301,6 +1354,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
1301 } 1354 }
1302 switch (w->id) { 1355 switch (w->id) {
1303 case snd_soc_dapm_supply: 1356 case snd_soc_dapm_supply:
1357 case snd_soc_dapm_regulator_supply:
1304 /* Supplies can't affect their outputs, only their inputs */ 1358 /* Supplies can't affect their outputs, only their inputs */
1305 break; 1359 break;
1306 default: 1360 default:
@@ -1373,13 +1427,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1373 } 1427 }
1374 } 1428 }
1375 1429
1376 memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); 1430 dapm_reset(card);
1377
1378 list_for_each_entry(w, &card->widgets, list) {
1379 w->power_checked = false;
1380 w->inputs = -1;
1381 w->outputs = -1;
1382 }
1383 1431
1384 /* Check which widgets we need to power and store them in 1432 /* Check which widgets we need to power and store them in
1385 * lists indicating if they should be powered up or down. We 1433 * lists indicating if they should be powered up or down. We
@@ -1400,10 +1448,15 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1400 /* Supplies and micbiases only bring the 1448 /* Supplies and micbiases only bring the
1401 * context up to STANDBY as unless something 1449 * context up to STANDBY as unless something
1402 * else is active and passing audio they 1450 * else is active and passing audio they
1403 * generally don't require full power. 1451 * generally don't require full power. Signal
1452 * generators are virtual pins and have no
1453 * power impact themselves.
1404 */ 1454 */
1405 switch (w->id) { 1455 switch (w->id) {
1456 case snd_soc_dapm_siggen:
1457 break;
1406 case snd_soc_dapm_supply: 1458 case snd_soc_dapm_supply:
1459 case snd_soc_dapm_regulator_supply:
1407 case snd_soc_dapm_micbias: 1460 case snd_soc_dapm_micbias:
1408 if (d->target_bias_level < SND_SOC_BIAS_STANDBY) 1461 if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
1409 d->target_bias_level = SND_SOC_BIAS_STANDBY; 1462 d->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1475,6 +1528,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1475 &async_domain); 1528 &async_domain);
1476 async_synchronize_full_domain(&async_domain); 1529 async_synchronize_full_domain(&async_domain);
1477 1530
1531 /* do we need to notify any clients that DAPM event is complete */
1532 list_for_each_entry(d, &card->dapm_list, list) {
1533 if (d->stream_event)
1534 d->stream_event(d, event);
1535 }
1536
1478 pop_dbg(dapm->dev, card->pop_time, 1537 pop_dbg(dapm->dev, card->pop_time,
1479 "DAPM sequencing finished, waiting %dms\n", card->pop_time); 1538 "DAPM sequencing finished, waiting %dms\n", card->pop_time);
1480 pop_wait(card->pop_time); 1539 pop_wait(card->pop_time);
@@ -1485,12 +1544,6 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1485} 1544}
1486 1545
1487#ifdef CONFIG_DEBUG_FS 1546#ifdef CONFIG_DEBUG_FS
1488static int dapm_widget_power_open_file(struct inode *inode, struct file *file)
1489{
1490 file->private_data = inode->i_private;
1491 return 0;
1492}
1493
1494static ssize_t dapm_widget_power_read_file(struct file *file, 1547static ssize_t dapm_widget_power_read_file(struct file *file,
1495 char __user *user_buf, 1548 char __user *user_buf,
1496 size_t count, loff_t *ppos) 1549 size_t count, loff_t *ppos)
@@ -1510,8 +1563,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1510 out = is_connected_output_ep(w); 1563 out = is_connected_output_ep(w);
1511 dapm_clear_walk(w->dapm); 1564 dapm_clear_walk(w->dapm);
1512 1565
1513 ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d", 1566 ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
1514 w->name, w->power ? "On" : "Off", in, out); 1567 w->name, w->power ? "On" : "Off",
1568 w->force ? " (forced)" : "", in, out);
1515 1569
1516 if (w->reg >= 0) 1570 if (w->reg >= 0)
1517 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1571 ret += snprintf(buf + ret, PAGE_SIZE - ret,
@@ -1553,17 +1607,11 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1553} 1607}
1554 1608
1555static const struct file_operations dapm_widget_power_fops = { 1609static const struct file_operations dapm_widget_power_fops = {
1556 .open = dapm_widget_power_open_file, 1610 .open = simple_open,
1557 .read = dapm_widget_power_read_file, 1611 .read = dapm_widget_power_read_file,
1558 .llseek = default_llseek, 1612 .llseek = default_llseek,
1559}; 1613};
1560 1614
1561static int dapm_bias_open_file(struct inode *inode, struct file *file)
1562{
1563 file->private_data = inode->i_private;
1564 return 0;
1565}
1566
1567static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf, 1615static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,
1568 size_t count, loff_t *ppos) 1616 size_t count, loff_t *ppos)
1569{ 1617{
@@ -1594,7 +1642,7 @@ static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,
1594} 1642}
1595 1643
1596static const struct file_operations dapm_bias_fops = { 1644static const struct file_operations dapm_bias_fops = {
1597 .open = dapm_bias_open_file, 1645 .open = simple_open,
1598 .read = dapm_bias_read_file, 1646 .read = dapm_bias_read_file,
1599 .llseek = default_llseek, 1647 .llseek = default_llseek,
1600}; 1648};
@@ -1607,7 +1655,7 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
1607 dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); 1655 dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);
1608 1656
1609 if (!dapm->debugfs_dapm) { 1657 if (!dapm->debugfs_dapm) {
1610 printk(KERN_WARNING 1658 dev_warn(dapm->dev,
1611 "Failed to create DAPM debugfs directory\n"); 1659 "Failed to create DAPM debugfs directory\n");
1612 return; 1660 return;
1613 } 1661 }
@@ -1659,9 +1707,8 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
1659#endif 1707#endif
1660 1708
1661/* test and update the power status of a mux widget */ 1709/* test and update the power status of a mux widget */
1662static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 1710int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1663 struct snd_kcontrol *kcontrol, int change, 1711 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
1664 int mux, struct soc_enum *e)
1665{ 1712{
1666 struct snd_soc_dapm_path *path; 1713 struct snd_soc_dapm_path *path;
1667 int found = 0; 1714 int found = 0;
@@ -1671,9 +1718,6 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1671 widget->id != snd_soc_dapm_value_mux) 1718 widget->id != snd_soc_dapm_value_mux)
1672 return -ENODEV; 1719 return -ENODEV;
1673 1720
1674 if (!change)
1675 return 0;
1676
1677 /* find dapm widget path assoc with kcontrol */ 1721 /* find dapm widget path assoc with kcontrol */
1678 list_for_each_entry(path, &widget->dapm->card->paths, list) { 1722 list_for_each_entry(path, &widget->dapm->card->paths, list) {
1679 if (path->kcontrol != kcontrol) 1723 if (path->kcontrol != kcontrol)
@@ -1702,9 +1746,10 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1702 1746
1703 return 0; 1747 return 0;
1704} 1748}
1749EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
1705 1750
1706/* test and update the power status of a mixer or switch widget */ 1751/* test and update the power status of a mixer or switch widget */
1707static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 1752int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1708 struct snd_kcontrol *kcontrol, int connect) 1753 struct snd_kcontrol *kcontrol, int connect)
1709{ 1754{
1710 struct snd_soc_dapm_path *path; 1755 struct snd_soc_dapm_path *path;
@@ -1733,6 +1778,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1733 1778
1734 return 0; 1779 return 0;
1735} 1780}
1781EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
1736 1782
1737/* show dapm widget status in sys fs */ 1783/* show dapm widget status in sys fs */
1738static ssize_t dapm_widget_show(struct device *dev, 1784static ssize_t dapm_widget_show(struct device *dev,
@@ -1762,6 +1808,7 @@ static ssize_t dapm_widget_show(struct device *dev,
1762 case snd_soc_dapm_mixer: 1808 case snd_soc_dapm_mixer:
1763 case snd_soc_dapm_mixer_named_ctl: 1809 case snd_soc_dapm_mixer_named_ctl:
1764 case snd_soc_dapm_supply: 1810 case snd_soc_dapm_supply:
1811 case snd_soc_dapm_regulator_supply:
1765 if (w->name) 1812 if (w->name)
1766 count += sprintf(buf + count, "%s: %s\n", 1813 count += sprintf(buf + count, "%s: %s\n",
1767 w->name, w->power ? "On":"Off"); 1814 w->name, w->power ? "On":"Off");
@@ -1869,10 +1916,12 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
1869 return -EINVAL; 1916 return -EINVAL;
1870 } 1917 }
1871 1918
1919 if (w->connected != status)
1920 dapm_mark_dirty(w, "pin configuration");
1921
1872 w->connected = status; 1922 w->connected = status;
1873 if (status == 0) 1923 if (status == 0)
1874 w->force = 0; 1924 w->force = 0;
1875 dapm_mark_dirty(w, "pin configuration");
1876 1925
1877 return 0; 1926 return 0;
1878} 1927}
@@ -2000,8 +2049,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2000 case snd_soc_dapm_pre: 2049 case snd_soc_dapm_pre:
2001 case snd_soc_dapm_post: 2050 case snd_soc_dapm_post:
2002 case snd_soc_dapm_supply: 2051 case snd_soc_dapm_supply:
2052 case snd_soc_dapm_regulator_supply:
2003 case snd_soc_dapm_aif_in: 2053 case snd_soc_dapm_aif_in:
2004 case snd_soc_dapm_aif_out: 2054 case snd_soc_dapm_aif_out:
2055 case snd_soc_dapm_dai:
2005 list_add(&path->list, &dapm->card->paths); 2056 list_add(&path->list, &dapm->card->paths);
2006 list_add(&path->list_sink, &wsink->sources); 2057 list_add(&path->list_sink, &wsink->sources);
2007 list_add(&path->list_source, &wsource->sinks); 2058 list_add(&path->list_source, &wsource->sinks);
@@ -2315,7 +2366,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2315 update.val = val; 2366 update.val = val;
2316 widget->dapm->update = &update; 2367 widget->dapm->update = &update;
2317 2368
2318 dapm_mixer_update_power(widget, kcontrol, connect); 2369 snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
2319 2370
2320 widget->dapm->update = NULL; 2371 widget->dapm->update = NULL;
2321 } 2372 }
@@ -2406,7 +2457,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2406 update.val = val; 2457 update.val = val;
2407 widget->dapm->update = &update; 2458 widget->dapm->update = &update;
2408 2459
2409 dapm_mux_update_power(widget, kcontrol, change, mux, e); 2460 snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
2410 2461
2411 widget->dapm->update = NULL; 2462 widget->dapm->update = NULL;
2412 } 2463 }
@@ -2467,8 +2518,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
2467 2518
2468 widget->value = ucontrol->value.enumerated.item[0]; 2519 widget->value = ucontrol->value.enumerated.item[0];
2469 2520
2470 dapm_mux_update_power(widget, kcontrol, change, 2521 snd_soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
2471 widget->value, e);
2472 } 2522 }
2473 } 2523 }
2474 2524
@@ -2571,7 +2621,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
2571 update.val = val; 2621 update.val = val;
2572 widget->dapm->update = &update; 2622 widget->dapm->update = &update;
2573 2623
2574 dapm_mux_update_power(widget, kcontrol, change, mux, e); 2624 snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
2575 2625
2576 widget->dapm->update = NULL; 2626 widget->dapm->update = NULL;
2577 } 2627 }
@@ -2611,15 +2661,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
2611int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, 2661int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
2612 struct snd_ctl_elem_value *ucontrol) 2662 struct snd_ctl_elem_value *ucontrol)
2613{ 2663{
2614 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2664 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
2615 const char *pin = (const char *)kcontrol->private_value; 2665 const char *pin = (const char *)kcontrol->private_value;
2616 2666
2617 mutex_lock(&codec->mutex); 2667 mutex_lock(&card->mutex);
2618 2668
2619 ucontrol->value.integer.value[0] = 2669 ucontrol->value.integer.value[0] =
2620 snd_soc_dapm_get_pin_status(&codec->dapm, pin); 2670 snd_soc_dapm_get_pin_status(&card->dapm, pin);
2621 2671
2622 mutex_unlock(&codec->mutex); 2672 mutex_unlock(&card->mutex);
2623 2673
2624 return 0; 2674 return 0;
2625} 2675}
@@ -2634,41 +2684,48 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
2634int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, 2684int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
2635 struct snd_ctl_elem_value *ucontrol) 2685 struct snd_ctl_elem_value *ucontrol)
2636{ 2686{
2637 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2687 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
2638 const char *pin = (const char *)kcontrol->private_value; 2688 const char *pin = (const char *)kcontrol->private_value;
2639 2689
2640 mutex_lock(&codec->mutex); 2690 mutex_lock(&card->mutex);
2641 2691
2642 if (ucontrol->value.integer.value[0]) 2692 if (ucontrol->value.integer.value[0])
2643 snd_soc_dapm_enable_pin(&codec->dapm, pin); 2693 snd_soc_dapm_enable_pin(&card->dapm, pin);
2644 else 2694 else
2645 snd_soc_dapm_disable_pin(&codec->dapm, pin); 2695 snd_soc_dapm_disable_pin(&card->dapm, pin);
2646 2696
2647 snd_soc_dapm_sync(&codec->dapm); 2697 snd_soc_dapm_sync(&card->dapm);
2648 2698
2649 mutex_unlock(&codec->mutex); 2699 mutex_unlock(&card->mutex);
2650 2700
2651 return 0; 2701 return 0;
2652} 2702}
2653EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); 2703EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
2654 2704
2655/** 2705static struct snd_soc_dapm_widget *
2656 * snd_soc_dapm_new_control - create new dapm control 2706snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2657 * @dapm: DAPM context 2707 const struct snd_soc_dapm_widget *widget)
2658 * @widget: widget template
2659 *
2660 * Creates a new dapm control based upon the template.
2661 *
2662 * Returns 0 for success else error.
2663 */
2664int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2665 const struct snd_soc_dapm_widget *widget)
2666{ 2708{
2667 struct snd_soc_dapm_widget *w; 2709 struct snd_soc_dapm_widget *w;
2668 size_t name_len; 2710 size_t name_len;
2711 int ret;
2669 2712
2670 if ((w = dapm_cnew_widget(widget)) == NULL) 2713 if ((w = dapm_cnew_widget(widget)) == NULL)
2671 return -ENOMEM; 2714 return NULL;
2715
2716 switch (w->id) {
2717 case snd_soc_dapm_regulator_supply:
2718 w->priv = devm_regulator_get(dapm->dev, w->name);
2719 if (IS_ERR(w->priv)) {
2720 ret = PTR_ERR(w->priv);
2721 dev_err(dapm->dev, "Failed to request %s: %d\n",
2722 w->name, ret);
2723 return NULL;
2724 }
2725 break;
2726 default:
2727 break;
2728 }
2672 2729
2673 name_len = strlen(widget->name) + 1; 2730 name_len = strlen(widget->name) + 1;
2674 if (dapm->codec && dapm->codec->name_prefix) 2731 if (dapm->codec && dapm->codec->name_prefix)
@@ -2676,13 +2733,13 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2676 w->name = kmalloc(name_len, GFP_KERNEL); 2733 w->name = kmalloc(name_len, GFP_KERNEL);
2677 if (w->name == NULL) { 2734 if (w->name == NULL) {
2678 kfree(w); 2735 kfree(w);
2679 return -ENOMEM; 2736 return NULL;
2680 } 2737 }
2681 if (dapm->codec && dapm->codec->name_prefix) 2738 if (dapm->codec && dapm->codec->name_prefix)
2682 snprintf(w->name, name_len, "%s %s", 2739 snprintf((char *)w->name, name_len, "%s %s",
2683 dapm->codec->name_prefix, widget->name); 2740 dapm->codec->name_prefix, widget->name);
2684 else 2741 else
2685 snprintf(w->name, name_len, "%s", widget->name); 2742 snprintf((char *)w->name, name_len, "%s", widget->name);
2686 2743
2687 switch (w->id) { 2744 switch (w->id) {
2688 case snd_soc_dapm_switch: 2745 case snd_soc_dapm_switch:
@@ -2715,8 +2772,12 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2715 w->power_check = dapm_generic_check_power; 2772 w->power_check = dapm_generic_check_power;
2716 break; 2773 break;
2717 case snd_soc_dapm_supply: 2774 case snd_soc_dapm_supply:
2775 case snd_soc_dapm_regulator_supply:
2718 w->power_check = dapm_supply_check_power; 2776 w->power_check = dapm_supply_check_power;
2719 break; 2777 break;
2778 case snd_soc_dapm_dai:
2779 w->power_check = dapm_dai_check_power;
2780 break;
2720 default: 2781 default:
2721 w->power_check = dapm_always_on_check_power; 2782 w->power_check = dapm_always_on_check_power;
2722 break; 2783 break;
@@ -2734,9 +2795,8 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2734 2795
2735 /* machine layer set ups unconnected pins and insertions */ 2796 /* machine layer set ups unconnected pins and insertions */
2736 w->connected = 1; 2797 w->connected = 1;
2737 return 0; 2798 return w;
2738} 2799}
2739EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
2740 2800
2741/** 2801/**
2742 * snd_soc_dapm_new_controls - create new dapm controls 2802 * snd_soc_dapm_new_controls - create new dapm controls
@@ -2752,15 +2812,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
2752 const struct snd_soc_dapm_widget *widget, 2812 const struct snd_soc_dapm_widget *widget,
2753 int num) 2813 int num)
2754{ 2814{
2755 int i, ret; 2815 struct snd_soc_dapm_widget *w;
2816 int i;
2756 2817
2757 for (i = 0; i < num; i++) { 2818 for (i = 0; i < num; i++) {
2758 ret = snd_soc_dapm_new_control(dapm, widget); 2819 w = snd_soc_dapm_new_control(dapm, widget);
2759 if (ret < 0) { 2820 if (!w) {
2760 dev_err(dapm->dev, 2821 dev_err(dapm->dev,
2761 "ASoC: Failed to create DAPM control %s: %d\n", 2822 "ASoC: Failed to create DAPM control %s\n",
2762 widget->name, ret); 2823 widget->name);
2763 return ret; 2824 return -ENOMEM;
2764 } 2825 }
2765 widget++; 2826 widget++;
2766 } 2827 }
@@ -2768,40 +2829,140 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
2768} 2829}
2769EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); 2830EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
2770 2831
2771static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm, 2832int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
2772 const char *stream, int event) 2833 struct snd_soc_dai *dai)
2773{ 2834{
2835 struct snd_soc_dapm_widget template;
2774 struct snd_soc_dapm_widget *w; 2836 struct snd_soc_dapm_widget *w;
2775 2837
2776 list_for_each_entry(w, &dapm->card->widgets, list) 2838 WARN_ON(dapm->dev != dai->dev);
2777 { 2839
2778 if (!w->sname || w->dapm != dapm) 2840 memset(&template, 0, sizeof(template));
2841 template.reg = SND_SOC_NOPM;
2842
2843 if (dai->driver->playback.stream_name) {
2844 template.id = snd_soc_dapm_dai;
2845 template.name = dai->driver->playback.stream_name;
2846 template.sname = dai->driver->playback.stream_name;
2847
2848 dev_dbg(dai->dev, "adding %s widget\n",
2849 template.name);
2850
2851 w = snd_soc_dapm_new_control(dapm, &template);
2852 if (!w) {
2853 dev_err(dapm->dev, "Failed to create %s widget\n",
2854 dai->driver->playback.stream_name);
2855 }
2856
2857 w->priv = dai;
2858 dai->playback_widget = w;
2859 }
2860
2861 if (dai->driver->capture.stream_name) {
2862 template.id = snd_soc_dapm_dai;
2863 template.name = dai->driver->capture.stream_name;
2864 template.sname = dai->driver->capture.stream_name;
2865
2866 dev_dbg(dai->dev, "adding %s widget\n",
2867 template.name);
2868
2869 w = snd_soc_dapm_new_control(dapm, &template);
2870 if (!w) {
2871 dev_err(dapm->dev, "Failed to create %s widget\n",
2872 dai->driver->capture.stream_name);
2873 }
2874
2875 w->priv = dai;
2876 dai->capture_widget = w;
2877 }
2878
2879 return 0;
2880}
2881
2882int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
2883{
2884 struct snd_soc_dapm_widget *dai_w, *w;
2885 struct snd_soc_dai *dai;
2886 struct snd_soc_dapm_route r;
2887
2888 memset(&r, 0, sizeof(r));
2889
2890 /* For each DAI widget... */
2891 list_for_each_entry(dai_w, &card->widgets, list) {
2892 if (dai_w->id != snd_soc_dapm_dai)
2779 continue; 2893 continue;
2780 dev_vdbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n", 2894
2781 w->name, w->sname, stream, event); 2895 dai = dai_w->priv;
2782 if (strstr(w->sname, stream)) { 2896
2783 dapm_mark_dirty(w, "stream event"); 2897 /* ...find all widgets with the same stream and link them */
2784 switch(event) { 2898 list_for_each_entry(w, &card->widgets, list) {
2785 case SND_SOC_DAPM_STREAM_START: 2899 if (w->dapm != dai_w->dapm)
2786 w->active = 1; 2900 continue;
2787 break; 2901
2788 case SND_SOC_DAPM_STREAM_STOP: 2902 if (w->id == snd_soc_dapm_dai)
2789 w->active = 0; 2903 continue;
2790 break; 2904
2791 case SND_SOC_DAPM_STREAM_SUSPEND: 2905 if (!w->sname)
2792 case SND_SOC_DAPM_STREAM_RESUME: 2906 continue;
2793 case SND_SOC_DAPM_STREAM_PAUSE_PUSH: 2907
2794 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: 2908 if (dai->driver->playback.stream_name &&
2795 break; 2909 strstr(w->sname,
2910 dai->driver->playback.stream_name)) {
2911 r.source = dai->playback_widget->name;
2912 r.sink = w->name;
2913 dev_dbg(dai->dev, "%s -> %s\n",
2914 r.source, r.sink);
2915
2916 snd_soc_dapm_add_route(w->dapm, &r);
2917 }
2918
2919 if (dai->driver->capture.stream_name &&
2920 strstr(w->sname,
2921 dai->driver->capture.stream_name)) {
2922 r.source = w->name;
2923 r.sink = dai->capture_widget->name;
2924 dev_dbg(dai->dev, "%s -> %s\n",
2925 r.source, r.sink);
2926
2927 snd_soc_dapm_add_route(w->dapm, &r);
2796 } 2928 }
2797 } 2929 }
2798 } 2930 }
2799 2931
2800 dapm_power_widgets(dapm, event); 2932 return 0;
2933}
2934
2935static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
2936 int stream, struct snd_soc_dai *dai,
2937 int event)
2938{
2939 struct snd_soc_dapm_widget *w;
2940
2941 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
2942 w = dai->playback_widget;
2943 else
2944 w = dai->capture_widget;
2945
2946 if (!w)
2947 return;
2948
2949 dapm_mark_dirty(w, "stream event");
2801 2950
2802 /* do we need to notify any clients that DAPM stream is complete */ 2951 switch (event) {
2803 if (dapm->stream_event) 2952 case SND_SOC_DAPM_STREAM_START:
2804 dapm->stream_event(dapm, event); 2953 w->active = 1;
2954 break;
2955 case SND_SOC_DAPM_STREAM_STOP:
2956 w->active = 0;
2957 break;
2958 case SND_SOC_DAPM_STREAM_SUSPEND:
2959 case SND_SOC_DAPM_STREAM_RESUME:
2960 case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
2961 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
2962 break;
2963 }
2964
2965 dapm_power_widgets(dapm, event);
2805} 2966}
2806 2967
2807/** 2968/**
@@ -2815,16 +2976,13 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
2815 * 2976 *
2816 * Returns 0 for success else error. 2977 * Returns 0 for success else error.
2817 */ 2978 */
2818int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, 2979int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
2819 const char *stream, int event) 2980 struct snd_soc_dai *dai, int event)
2820{ 2981{
2821 struct snd_soc_codec *codec = rtd->codec; 2982 struct snd_soc_codec *codec = rtd->codec;
2822 2983
2823 if (stream == NULL)
2824 return 0;
2825
2826 mutex_lock(&codec->mutex); 2984 mutex_lock(&codec->mutex);
2827 soc_dapm_stream_event(&codec->dapm, stream, event); 2985 soc_dapm_stream_event(&codec->dapm, stream, dai, event);
2828 mutex_unlock(&codec->mutex); 2986 mutex_unlock(&codec->mutex);
2829 return 0; 2987 return 0;
2830} 2988}
@@ -3068,9 +3226,13 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
3068 * standby. 3226 * standby.
3069 */ 3227 */
3070 if (powerdown) { 3228 if (powerdown) {
3071 snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_PREPARE); 3229 if (dapm->bias_level == SND_SOC_BIAS_ON)
3230 snd_soc_dapm_set_bias_level(dapm,
3231 SND_SOC_BIAS_PREPARE);
3072 dapm_seq_run(dapm, &down_list, 0, false); 3232 dapm_seq_run(dapm, &down_list, 0, false);
3073 snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_STANDBY); 3233 if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
3234 snd_soc_dapm_set_bias_level(dapm,
3235 SND_SOC_BIAS_STANDBY);
3074 } 3236 }
3075} 3237}
3076 3238
@@ -3083,7 +3245,9 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card)
3083 3245
3084 list_for_each_entry(codec, &card->codec_dev_list, list) { 3246 list_for_each_entry(codec, &card->codec_dev_list, list) {
3085 soc_dapm_shutdown_codec(&codec->dapm); 3247 soc_dapm_shutdown_codec(&codec->dapm);
3086 snd_soc_dapm_set_bias_level(&codec->dapm, SND_SOC_BIAS_OFF); 3248 if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
3249 snd_soc_dapm_set_bias_level(&codec->dapm,
3250 SND_SOC_BIAS_OFF);
3087 } 3251 }
3088} 3252}
3089 3253