aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-03-24 07:33:59 -0400
committerOlof Johansson <olof@lixom.net>2012-03-27 18:18:19 -0400
commita754a87ce8b17024358c1be8ee0232ef09a7055f (patch)
treec0d4adee8f490828ca04cd45d6fbb13596d88322 /sound/soc/soc-dapm.c
parent70688056a8b4d610249716befe262a74fd123d90 (diff)
parent22f8d055350066b4a87de4adea8c5213cac54534 (diff)
Merge tag 'asoc-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into next/boards
The asoc branch that was already merged into v3.4 contains some board-level changes that conflict with patches we already have here, so pull in that branch to resolve the conflicts. Conflicts: arch/arm/mach-imx/mach-imx27_visstrim_m10.c arch/arm/mach-omap2/board-omap4panda.c Signed-off-by: Arnd Bergmann <arnd@arndb.de> [olof: Amended fix for mismerge as reported by Kevin Hilman] Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c400
1 files changed, 285 insertions, 115 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1315663c1c09..6241490fff30 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);
@@ -1510,8 +1569,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1510 out = is_connected_output_ep(w); 1569 out = is_connected_output_ep(w);
1511 dapm_clear_walk(w->dapm); 1570 dapm_clear_walk(w->dapm);
1512 1571
1513 ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d", 1572 ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
1514 w->name, w->power ? "On" : "Off", in, out); 1573 w->name, w->power ? "On" : "Off",
1574 w->force ? " (forced)" : "", in, out);
1515 1575
1516 if (w->reg >= 0) 1576 if (w->reg >= 0)
1517 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1577 ret += snprintf(buf + ret, PAGE_SIZE - ret,
@@ -1607,7 +1667,7 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
1607 dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); 1667 dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);
1608 1668
1609 if (!dapm->debugfs_dapm) { 1669 if (!dapm->debugfs_dapm) {
1610 printk(KERN_WARNING 1670 dev_warn(dapm->dev,
1611 "Failed to create DAPM debugfs directory\n"); 1671 "Failed to create DAPM debugfs directory\n");
1612 return; 1672 return;
1613 } 1673 }
@@ -1659,9 +1719,8 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
1659#endif 1719#endif
1660 1720
1661/* test and update the power status of a mux widget */ 1721/* test and update the power status of a mux widget */
1662static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 1722int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1663 struct snd_kcontrol *kcontrol, int change, 1723 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
1664 int mux, struct soc_enum *e)
1665{ 1724{
1666 struct snd_soc_dapm_path *path; 1725 struct snd_soc_dapm_path *path;
1667 int found = 0; 1726 int found = 0;
@@ -1671,9 +1730,6 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1671 widget->id != snd_soc_dapm_value_mux) 1730 widget->id != snd_soc_dapm_value_mux)
1672 return -ENODEV; 1731 return -ENODEV;
1673 1732
1674 if (!change)
1675 return 0;
1676
1677 /* find dapm widget path assoc with kcontrol */ 1733 /* find dapm widget path assoc with kcontrol */
1678 list_for_each_entry(path, &widget->dapm->card->paths, list) { 1734 list_for_each_entry(path, &widget->dapm->card->paths, list) {
1679 if (path->kcontrol != kcontrol) 1735 if (path->kcontrol != kcontrol)
@@ -1702,9 +1758,10 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1702 1758
1703 return 0; 1759 return 0;
1704} 1760}
1761EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
1705 1762
1706/* test and update the power status of a mixer or switch widget */ 1763/* test and update the power status of a mixer or switch widget */
1707static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 1764int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1708 struct snd_kcontrol *kcontrol, int connect) 1765 struct snd_kcontrol *kcontrol, int connect)
1709{ 1766{
1710 struct snd_soc_dapm_path *path; 1767 struct snd_soc_dapm_path *path;
@@ -1733,6 +1790,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1733 1790
1734 return 0; 1791 return 0;
1735} 1792}
1793EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
1736 1794
1737/* show dapm widget status in sys fs */ 1795/* show dapm widget status in sys fs */
1738static ssize_t dapm_widget_show(struct device *dev, 1796static ssize_t dapm_widget_show(struct device *dev,
@@ -1762,6 +1820,7 @@ static ssize_t dapm_widget_show(struct device *dev,
1762 case snd_soc_dapm_mixer: 1820 case snd_soc_dapm_mixer:
1763 case snd_soc_dapm_mixer_named_ctl: 1821 case snd_soc_dapm_mixer_named_ctl:
1764 case snd_soc_dapm_supply: 1822 case snd_soc_dapm_supply:
1823 case snd_soc_dapm_regulator_supply:
1765 if (w->name) 1824 if (w->name)
1766 count += sprintf(buf + count, "%s: %s\n", 1825 count += sprintf(buf + count, "%s: %s\n",
1767 w->name, w->power ? "On":"Off"); 1826 w->name, w->power ? "On":"Off");
@@ -1869,10 +1928,12 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
1869 return -EINVAL; 1928 return -EINVAL;
1870 } 1929 }
1871 1930
1931 if (w->connected != status)
1932 dapm_mark_dirty(w, "pin configuration");
1933
1872 w->connected = status; 1934 w->connected = status;
1873 if (status == 0) 1935 if (status == 0)
1874 w->force = 0; 1936 w->force = 0;
1875 dapm_mark_dirty(w, "pin configuration");
1876 1937
1877 return 0; 1938 return 0;
1878} 1939}
@@ -2000,8 +2061,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2000 case snd_soc_dapm_pre: 2061 case snd_soc_dapm_pre:
2001 case snd_soc_dapm_post: 2062 case snd_soc_dapm_post:
2002 case snd_soc_dapm_supply: 2063 case snd_soc_dapm_supply:
2064 case snd_soc_dapm_regulator_supply:
2003 case snd_soc_dapm_aif_in: 2065 case snd_soc_dapm_aif_in:
2004 case snd_soc_dapm_aif_out: 2066 case snd_soc_dapm_aif_out:
2067 case snd_soc_dapm_dai:
2005 list_add(&path->list, &dapm->card->paths); 2068 list_add(&path->list, &dapm->card->paths);
2006 list_add(&path->list_sink, &wsink->sources); 2069 list_add(&path->list_sink, &wsink->sources);
2007 list_add(&path->list_source, &wsource->sinks); 2070 list_add(&path->list_source, &wsource->sinks);
@@ -2315,7 +2378,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2315 update.val = val; 2378 update.val = val;
2316 widget->dapm->update = &update; 2379 widget->dapm->update = &update;
2317 2380
2318 dapm_mixer_update_power(widget, kcontrol, connect); 2381 snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
2319 2382
2320 widget->dapm->update = NULL; 2383 widget->dapm->update = NULL;
2321 } 2384 }
@@ -2406,7 +2469,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2406 update.val = val; 2469 update.val = val;
2407 widget->dapm->update = &update; 2470 widget->dapm->update = &update;
2408 2471
2409 dapm_mux_update_power(widget, kcontrol, change, mux, e); 2472 snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
2410 2473
2411 widget->dapm->update = NULL; 2474 widget->dapm->update = NULL;
2412 } 2475 }
@@ -2467,8 +2530,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
2467 2530
2468 widget->value = ucontrol->value.enumerated.item[0]; 2531 widget->value = ucontrol->value.enumerated.item[0];
2469 2532
2470 dapm_mux_update_power(widget, kcontrol, change, 2533 snd_soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
2471 widget->value, e);
2472 } 2534 }
2473 } 2535 }
2474 2536
@@ -2571,7 +2633,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
2571 update.val = val; 2633 update.val = val;
2572 widget->dapm->update = &update; 2634 widget->dapm->update = &update;
2573 2635
2574 dapm_mux_update_power(widget, kcontrol, change, mux, e); 2636 snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
2575 2637
2576 widget->dapm->update = NULL; 2638 widget->dapm->update = NULL;
2577 } 2639 }
@@ -2611,15 +2673,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
2611int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, 2673int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
2612 struct snd_ctl_elem_value *ucontrol) 2674 struct snd_ctl_elem_value *ucontrol)
2613{ 2675{
2614 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2676 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
2615 const char *pin = (const char *)kcontrol->private_value; 2677 const char *pin = (const char *)kcontrol->private_value;
2616 2678
2617 mutex_lock(&codec->mutex); 2679 mutex_lock(&card->mutex);
2618 2680
2619 ucontrol->value.integer.value[0] = 2681 ucontrol->value.integer.value[0] =
2620 snd_soc_dapm_get_pin_status(&codec->dapm, pin); 2682 snd_soc_dapm_get_pin_status(&card->dapm, pin);
2621 2683
2622 mutex_unlock(&codec->mutex); 2684 mutex_unlock(&card->mutex);
2623 2685
2624 return 0; 2686 return 0;
2625} 2687}
@@ -2634,41 +2696,48 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
2634int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, 2696int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
2635 struct snd_ctl_elem_value *ucontrol) 2697 struct snd_ctl_elem_value *ucontrol)
2636{ 2698{
2637 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2699 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
2638 const char *pin = (const char *)kcontrol->private_value; 2700 const char *pin = (const char *)kcontrol->private_value;
2639 2701
2640 mutex_lock(&codec->mutex); 2702 mutex_lock(&card->mutex);
2641 2703
2642 if (ucontrol->value.integer.value[0]) 2704 if (ucontrol->value.integer.value[0])
2643 snd_soc_dapm_enable_pin(&codec->dapm, pin); 2705 snd_soc_dapm_enable_pin(&card->dapm, pin);
2644 else 2706 else
2645 snd_soc_dapm_disable_pin(&codec->dapm, pin); 2707 snd_soc_dapm_disable_pin(&card->dapm, pin);
2646 2708
2647 snd_soc_dapm_sync(&codec->dapm); 2709 snd_soc_dapm_sync(&card->dapm);
2648 2710
2649 mutex_unlock(&codec->mutex); 2711 mutex_unlock(&card->mutex);
2650 2712
2651 return 0; 2713 return 0;
2652} 2714}
2653EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); 2715EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
2654 2716
2655/** 2717static struct snd_soc_dapm_widget *
2656 * snd_soc_dapm_new_control - create new dapm control 2718snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2657 * @dapm: DAPM context 2719 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{ 2720{
2667 struct snd_soc_dapm_widget *w; 2721 struct snd_soc_dapm_widget *w;
2668 size_t name_len; 2722 size_t name_len;
2723 int ret;
2669 2724
2670 if ((w = dapm_cnew_widget(widget)) == NULL) 2725 if ((w = dapm_cnew_widget(widget)) == NULL)
2671 return -ENOMEM; 2726 return NULL;
2727
2728 switch (w->id) {
2729 case snd_soc_dapm_regulator_supply:
2730 w->priv = devm_regulator_get(dapm->dev, w->name);
2731 if (IS_ERR(w->priv)) {
2732 ret = PTR_ERR(w->priv);
2733 dev_err(dapm->dev, "Failed to request %s: %d\n",
2734 w->name, ret);
2735 return NULL;
2736 }
2737 break;
2738 default:
2739 break;
2740 }
2672 2741
2673 name_len = strlen(widget->name) + 1; 2742 name_len = strlen(widget->name) + 1;
2674 if (dapm->codec && dapm->codec->name_prefix) 2743 if (dapm->codec && dapm->codec->name_prefix)
@@ -2676,13 +2745,13 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2676 w->name = kmalloc(name_len, GFP_KERNEL); 2745 w->name = kmalloc(name_len, GFP_KERNEL);
2677 if (w->name == NULL) { 2746 if (w->name == NULL) {
2678 kfree(w); 2747 kfree(w);
2679 return -ENOMEM; 2748 return NULL;
2680 } 2749 }
2681 if (dapm->codec && dapm->codec->name_prefix) 2750 if (dapm->codec && dapm->codec->name_prefix)
2682 snprintf(w->name, name_len, "%s %s", 2751 snprintf((char *)w->name, name_len, "%s %s",
2683 dapm->codec->name_prefix, widget->name); 2752 dapm->codec->name_prefix, widget->name);
2684 else 2753 else
2685 snprintf(w->name, name_len, "%s", widget->name); 2754 snprintf((char *)w->name, name_len, "%s", widget->name);
2686 2755
2687 switch (w->id) { 2756 switch (w->id) {
2688 case snd_soc_dapm_switch: 2757 case snd_soc_dapm_switch:
@@ -2715,8 +2784,12 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2715 w->power_check = dapm_generic_check_power; 2784 w->power_check = dapm_generic_check_power;
2716 break; 2785 break;
2717 case snd_soc_dapm_supply: 2786 case snd_soc_dapm_supply:
2787 case snd_soc_dapm_regulator_supply:
2718 w->power_check = dapm_supply_check_power; 2788 w->power_check = dapm_supply_check_power;
2719 break; 2789 break;
2790 case snd_soc_dapm_dai:
2791 w->power_check = dapm_dai_check_power;
2792 break;
2720 default: 2793 default:
2721 w->power_check = dapm_always_on_check_power; 2794 w->power_check = dapm_always_on_check_power;
2722 break; 2795 break;
@@ -2734,9 +2807,8 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2734 2807
2735 /* machine layer set ups unconnected pins and insertions */ 2808 /* machine layer set ups unconnected pins and insertions */
2736 w->connected = 1; 2809 w->connected = 1;
2737 return 0; 2810 return w;
2738} 2811}
2739EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
2740 2812
2741/** 2813/**
2742 * snd_soc_dapm_new_controls - create new dapm controls 2814 * snd_soc_dapm_new_controls - create new dapm controls
@@ -2752,15 +2824,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
2752 const struct snd_soc_dapm_widget *widget, 2824 const struct snd_soc_dapm_widget *widget,
2753 int num) 2825 int num)
2754{ 2826{
2755 int i, ret; 2827 struct snd_soc_dapm_widget *w;
2828 int i;
2756 2829
2757 for (i = 0; i < num; i++) { 2830 for (i = 0; i < num; i++) {
2758 ret = snd_soc_dapm_new_control(dapm, widget); 2831 w = snd_soc_dapm_new_control(dapm, widget);
2759 if (ret < 0) { 2832 if (!w) {
2760 dev_err(dapm->dev, 2833 dev_err(dapm->dev,
2761 "ASoC: Failed to create DAPM control %s: %d\n", 2834 "ASoC: Failed to create DAPM control %s\n",
2762 widget->name, ret); 2835 widget->name);
2763 return ret; 2836 return -ENOMEM;
2764 } 2837 }
2765 widget++; 2838 widget++;
2766 } 2839 }
@@ -2768,40 +2841,140 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
2768} 2841}
2769EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); 2842EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
2770 2843
2771static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm, 2844int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
2772 const char *stream, int event) 2845 struct snd_soc_dai *dai)
2773{ 2846{
2847 struct snd_soc_dapm_widget template;
2774 struct snd_soc_dapm_widget *w; 2848 struct snd_soc_dapm_widget *w;
2775 2849
2776 list_for_each_entry(w, &dapm->card->widgets, list) 2850 WARN_ON(dapm->dev != dai->dev);
2777 { 2851
2778 if (!w->sname || w->dapm != dapm) 2852 memset(&template, 0, sizeof(template));
2853 template.reg = SND_SOC_NOPM;
2854
2855 if (dai->driver->playback.stream_name) {
2856 template.id = snd_soc_dapm_dai;
2857 template.name = dai->driver->playback.stream_name;
2858 template.sname = dai->driver->playback.stream_name;
2859
2860 dev_dbg(dai->dev, "adding %s widget\n",
2861 template.name);
2862
2863 w = snd_soc_dapm_new_control(dapm, &template);
2864 if (!w) {
2865 dev_err(dapm->dev, "Failed to create %s widget\n",
2866 dai->driver->playback.stream_name);
2867 }
2868
2869 w->priv = dai;
2870 dai->playback_widget = w;
2871 }
2872
2873 if (dai->driver->capture.stream_name) {
2874 template.id = snd_soc_dapm_dai;
2875 template.name = dai->driver->capture.stream_name;
2876 template.sname = dai->driver->capture.stream_name;
2877
2878 dev_dbg(dai->dev, "adding %s widget\n",
2879 template.name);
2880
2881 w = snd_soc_dapm_new_control(dapm, &template);
2882 if (!w) {
2883 dev_err(dapm->dev, "Failed to create %s widget\n",
2884 dai->driver->capture.stream_name);
2885 }
2886
2887 w->priv = dai;
2888 dai->capture_widget = w;
2889 }
2890
2891 return 0;
2892}
2893
2894int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
2895{
2896 struct snd_soc_dapm_widget *dai_w, *w;
2897 struct snd_soc_dai *dai;
2898 struct snd_soc_dapm_route r;
2899
2900 memset(&r, 0, sizeof(r));
2901
2902 /* For each DAI widget... */
2903 list_for_each_entry(dai_w, &card->widgets, list) {
2904 if (dai_w->id != snd_soc_dapm_dai)
2779 continue; 2905 continue;
2780 dev_vdbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n", 2906
2781 w->name, w->sname, stream, event); 2907 dai = dai_w->priv;
2782 if (strstr(w->sname, stream)) { 2908
2783 dapm_mark_dirty(w, "stream event"); 2909 /* ...find all widgets with the same stream and link them */
2784 switch(event) { 2910 list_for_each_entry(w, &card->widgets, list) {
2785 case SND_SOC_DAPM_STREAM_START: 2911 if (w->dapm != dai_w->dapm)
2786 w->active = 1; 2912 continue;
2787 break; 2913
2788 case SND_SOC_DAPM_STREAM_STOP: 2914 if (w->id == snd_soc_dapm_dai)
2789 w->active = 0; 2915 continue;
2790 break; 2916
2791 case SND_SOC_DAPM_STREAM_SUSPEND: 2917 if (!w->sname)
2792 case SND_SOC_DAPM_STREAM_RESUME: 2918 continue;
2793 case SND_SOC_DAPM_STREAM_PAUSE_PUSH: 2919
2794 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: 2920 if (dai->driver->playback.stream_name &&
2795 break; 2921 strstr(w->sname,
2922 dai->driver->playback.stream_name)) {
2923 r.source = dai->playback_widget->name;
2924 r.sink = w->name;
2925 dev_dbg(dai->dev, "%s -> %s\n",
2926 r.source, r.sink);
2927
2928 snd_soc_dapm_add_route(w->dapm, &r);
2929 }
2930
2931 if (dai->driver->capture.stream_name &&
2932 strstr(w->sname,
2933 dai->driver->capture.stream_name)) {
2934 r.source = w->name;
2935 r.sink = dai->capture_widget->name;
2936 dev_dbg(dai->dev, "%s -> %s\n",
2937 r.source, r.sink);
2938
2939 snd_soc_dapm_add_route(w->dapm, &r);
2796 } 2940 }
2797 } 2941 }
2798 } 2942 }
2799 2943
2800 dapm_power_widgets(dapm, event); 2944 return 0;
2945}
2801 2946
2802 /* do we need to notify any clients that DAPM stream is complete */ 2947static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
2803 if (dapm->stream_event) 2948 int stream, struct snd_soc_dai *dai,
2804 dapm->stream_event(dapm, event); 2949 int event)
2950{
2951 struct snd_soc_dapm_widget *w;
2952
2953 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
2954 w = dai->playback_widget;
2955 else
2956 w = dai->capture_widget;
2957
2958 if (!w)
2959 return;
2960
2961 dapm_mark_dirty(w, "stream event");
2962
2963 switch (event) {
2964 case SND_SOC_DAPM_STREAM_START:
2965 w->active = 1;
2966 break;
2967 case SND_SOC_DAPM_STREAM_STOP:
2968 w->active = 0;
2969 break;
2970 case SND_SOC_DAPM_STREAM_SUSPEND:
2971 case SND_SOC_DAPM_STREAM_RESUME:
2972 case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
2973 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
2974 break;
2975 }
2976
2977 dapm_power_widgets(dapm, event);
2805} 2978}
2806 2979
2807/** 2980/**
@@ -2815,16 +2988,13 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
2815 * 2988 *
2816 * Returns 0 for success else error. 2989 * Returns 0 for success else error.
2817 */ 2990 */
2818int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, 2991int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
2819 const char *stream, int event) 2992 struct snd_soc_dai *dai, int event)
2820{ 2993{
2821 struct snd_soc_codec *codec = rtd->codec; 2994 struct snd_soc_codec *codec = rtd->codec;
2822 2995
2823 if (stream == NULL)
2824 return 0;
2825
2826 mutex_lock(&codec->mutex); 2996 mutex_lock(&codec->mutex);
2827 soc_dapm_stream_event(&codec->dapm, stream, event); 2997 soc_dapm_stream_event(&codec->dapm, stream, dai, event);
2828 mutex_unlock(&codec->mutex); 2998 mutex_unlock(&codec->mutex);
2829 return 0; 2999 return 0;
2830} 3000}