aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c578
1 files changed, 447 insertions, 131 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index dc7dbfe61cd0..90ee77d2409d 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -52,6 +52,7 @@ static int dapm_up_seq[] = {
52 [snd_soc_dapm_supply] = 1, 52 [snd_soc_dapm_supply] = 1,
53 [snd_soc_dapm_regulator_supply] = 1, 53 [snd_soc_dapm_regulator_supply] = 1,
54 [snd_soc_dapm_micbias] = 2, 54 [snd_soc_dapm_micbias] = 2,
55 [snd_soc_dapm_dai_link] = 2,
55 [snd_soc_dapm_dai] = 3, 56 [snd_soc_dapm_dai] = 3,
56 [snd_soc_dapm_aif_in] = 3, 57 [snd_soc_dapm_aif_in] = 3,
57 [snd_soc_dapm_aif_out] = 3, 58 [snd_soc_dapm_aif_out] = 3,
@@ -90,9 +91,10 @@ static int dapm_down_seq[] = {
90 [snd_soc_dapm_aif_in] = 10, 91 [snd_soc_dapm_aif_in] = 10,
91 [snd_soc_dapm_aif_out] = 10, 92 [snd_soc_dapm_aif_out] = 10,
92 [snd_soc_dapm_dai] = 10, 93 [snd_soc_dapm_dai] = 10,
93 [snd_soc_dapm_regulator_supply] = 11, 94 [snd_soc_dapm_dai_link] = 11,
94 [snd_soc_dapm_supply] = 11, 95 [snd_soc_dapm_regulator_supply] = 12,
95 [snd_soc_dapm_post] = 12, 96 [snd_soc_dapm_supply] = 12,
97 [snd_soc_dapm_post] = 13,
96}; 98};
97 99
98static void pop_wait(u32 pop_time) 100static void pop_wait(u32 pop_time)
@@ -208,7 +210,23 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
208 return -1; 210 return -1;
209} 211}
210 212
211static int soc_widget_update_bits(struct snd_soc_dapm_widget *w, 213static inline void soc_widget_lock(struct snd_soc_dapm_widget *w)
214{
215 if (w->codec && !w->codec->using_regmap)
216 mutex_lock(&w->codec->mutex);
217 else if (w->platform)
218 mutex_lock(&w->platform->mutex);
219}
220
221static inline void soc_widget_unlock(struct snd_soc_dapm_widget *w)
222{
223 if (w->codec && !w->codec->using_regmap)
224 mutex_unlock(&w->codec->mutex);
225 else if (w->platform)
226 mutex_unlock(&w->platform->mutex);
227}
228
229static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
212 unsigned short reg, unsigned int mask, unsigned int value) 230 unsigned short reg, unsigned int mask, unsigned int value)
213{ 231{
214 bool change; 232 bool change;
@@ -221,18 +239,24 @@ static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
221 if (ret != 0) 239 if (ret != 0)
222 return ret; 240 return ret;
223 } else { 241 } else {
242 soc_widget_lock(w);
224 ret = soc_widget_read(w, reg); 243 ret = soc_widget_read(w, reg);
225 if (ret < 0) 244 if (ret < 0) {
245 soc_widget_unlock(w);
226 return ret; 246 return ret;
247 }
227 248
228 old = ret; 249 old = ret;
229 new = (old & ~mask) | (value & mask); 250 new = (old & ~mask) | (value & mask);
230 change = old != new; 251 change = old != new;
231 if (change) { 252 if (change) {
232 ret = soc_widget_write(w, reg, new); 253 ret = soc_widget_write(w, reg, new);
233 if (ret < 0) 254 if (ret < 0) {
255 soc_widget_unlock(w);
234 return ret; 256 return ret;
257 }
235 } 258 }
259 soc_widget_unlock(w);
236 } 260 }
237 261
238 return change; 262 return change;
@@ -374,6 +398,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
374 case snd_soc_dapm_mic: 398 case snd_soc_dapm_mic:
375 case snd_soc_dapm_spk: 399 case snd_soc_dapm_spk:
376 case snd_soc_dapm_line: 400 case snd_soc_dapm_line:
401 case snd_soc_dapm_dai_link:
377 p->connect = 1; 402 p->connect = 1;
378 break; 403 break;
379 /* does affect routing - dynamically connected */ 404 /* does affect routing - dynamically connected */
@@ -682,11 +707,51 @@ static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
682 } 707 }
683} 708}
684 709
710/* add widget to list if it's not already in the list */
711static int dapm_list_add_widget(struct snd_soc_dapm_widget_list **list,
712 struct snd_soc_dapm_widget *w)
713{
714 struct snd_soc_dapm_widget_list *wlist;
715 int wlistsize, wlistentries, i;
716
717 if (*list == NULL)
718 return -EINVAL;
719
720 wlist = *list;
721
722 /* is this widget already in the list */
723 for (i = 0; i < wlist->num_widgets; i++) {
724 if (wlist->widgets[i] == w)
725 return 0;
726 }
727
728 /* allocate some new space */
729 wlistentries = wlist->num_widgets + 1;
730 wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
731 wlistentries * sizeof(struct snd_soc_dapm_widget *);
732 *list = krealloc(wlist, wlistsize, GFP_KERNEL);
733 if (*list == NULL) {
734 dev_err(w->dapm->dev, "can't allocate widget list for %s\n",
735 w->name);
736 return -ENOMEM;
737 }
738 wlist = *list;
739
740 /* insert the widget */
741 dev_dbg(w->dapm->dev, "added %s in widget list pos %d\n",
742 w->name, wlist->num_widgets);
743
744 wlist->widgets[wlist->num_widgets] = w;
745 wlist->num_widgets++;
746 return 1;
747}
748
685/* 749/*
686 * Recursively check for a completed path to an active or physically connected 750 * Recursively check for a completed path to an active or physically connected
687 * output widget. Returns number of complete paths. 751 * output widget. Returns number of complete paths.
688 */ 752 */
689static int is_connected_output_ep(struct snd_soc_dapm_widget *widget) 753static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
754 struct snd_soc_dapm_widget_list **list)
690{ 755{
691 struct snd_soc_dapm_path *path; 756 struct snd_soc_dapm_path *path;
692 int con = 0; 757 int con = 0;
@@ -742,9 +807,23 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
742 if (path->walked) 807 if (path->walked)
743 continue; 808 continue;
744 809
810 trace_snd_soc_dapm_output_path(widget, path);
811
745 if (path->sink && path->connect) { 812 if (path->sink && path->connect) {
746 path->walked = 1; 813 path->walked = 1;
747 con += is_connected_output_ep(path->sink); 814
815 /* do we need to add this widget to the list ? */
816 if (list) {
817 int err;
818 err = dapm_list_add_widget(list, path->sink);
819 if (err < 0) {
820 dev_err(widget->dapm->dev, "could not add widget %s\n",
821 widget->name);
822 return con;
823 }
824 }
825
826 con += is_connected_output_ep(path->sink, list);
748 } 827 }
749 } 828 }
750 829
@@ -757,7 +836,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
757 * Recursively check for a completed path to an active or physically connected 836 * Recursively check for a completed path to an active or physically connected
758 * input widget. Returns number of complete paths. 837 * input widget. Returns number of complete paths.
759 */ 838 */
760static int is_connected_input_ep(struct snd_soc_dapm_widget *widget) 839static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
840 struct snd_soc_dapm_widget_list **list)
761{ 841{
762 struct snd_soc_dapm_path *path; 842 struct snd_soc_dapm_path *path;
763 int con = 0; 843 int con = 0;
@@ -825,9 +905,23 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
825 if (path->walked) 905 if (path->walked)
826 continue; 906 continue;
827 907
908 trace_snd_soc_dapm_input_path(widget, path);
909
828 if (path->source && path->connect) { 910 if (path->source && path->connect) {
829 path->walked = 1; 911 path->walked = 1;
830 con += is_connected_input_ep(path->source); 912
913 /* do we need to add this widget to the list ? */
914 if (list) {
915 int err;
916 err = dapm_list_add_widget(list, path->sink);
917 if (err < 0) {
918 dev_err(widget->dapm->dev, "could not add widget %s\n",
919 widget->name);
920 return con;
921 }
922 }
923
924 con += is_connected_input_ep(path->source, list);
831 } 925 }
832 } 926 }
833 927
@@ -836,6 +930,39 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
836 return con; 930 return con;
837} 931}
838 932
933/**
934 * snd_soc_dapm_get_connected_widgets - query audio path and it's widgets.
935 * @dai: the soc DAI.
936 * @stream: stream direction.
937 * @list: list of active widgets for this stream.
938 *
939 * Queries DAPM graph as to whether an valid audio stream path exists for
940 * the initial stream specified by name. This takes into account
941 * current mixer and mux kcontrol settings. Creates list of valid widgets.
942 *
943 * Returns the number of valid paths or negative error.
944 */
945int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
946 struct snd_soc_dapm_widget_list **list)
947{
948 struct snd_soc_card *card = dai->card;
949 int paths;
950
951 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
952 dapm_reset(card);
953
954 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
955 paths = is_connected_output_ep(dai->playback_widget, list);
956 else
957 paths = is_connected_input_ep(dai->playback_widget, list);
958
959 trace_snd_soc_dapm_connected(paths, stream);
960 dapm_clear_walk(&card->dapm);
961 mutex_unlock(&card->dapm_mutex);
962
963 return paths;
964}
965
839/* 966/*
840 * Handler for generic register modifier widget. 967 * Handler for generic register modifier widget.
841 */ 968 */
@@ -849,7 +976,7 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
849 else 976 else
850 val = w->off_val; 977 val = w->off_val;
851 978
852 soc_widget_update_bits(w, -(w->reg + 1), 979 soc_widget_update_bits_locked(w, -(w->reg + 1),
853 w->mask << w->shift, val << w->shift); 980 w->mask << w->shift, val << w->shift);
854 981
855 return 0; 982 return 0;
@@ -863,9 +990,9 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
863 struct snd_kcontrol *kcontrol, int event) 990 struct snd_kcontrol *kcontrol, int event)
864{ 991{
865 if (SND_SOC_DAPM_EVENT_ON(event)) 992 if (SND_SOC_DAPM_EVENT_ON(event))
866 return regulator_enable(w->priv); 993 return regulator_enable(w->regulator);
867 else 994 else
868 return regulator_disable_deferred(w->priv, w->shift); 995 return regulator_disable_deferred(w->regulator, w->shift);
869} 996}
870EXPORT_SYMBOL_GPL(dapm_regulator_event); 997EXPORT_SYMBOL_GPL(dapm_regulator_event);
871 998
@@ -892,9 +1019,9 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
892 1019
893 DAPM_UPDATE_STAT(w, power_checks); 1020 DAPM_UPDATE_STAT(w, power_checks);
894 1021
895 in = is_connected_input_ep(w); 1022 in = is_connected_input_ep(w, NULL);
896 dapm_clear_walk(w->dapm); 1023 dapm_clear_walk(w->dapm);
897 out = is_connected_output_ep(w); 1024 out = is_connected_output_ep(w, NULL);
898 dapm_clear_walk(w->dapm); 1025 dapm_clear_walk(w->dapm);
899 return out != 0 && in != 0; 1026 return out != 0 && in != 0;
900} 1027}
@@ -903,7 +1030,10 @@ static int dapm_dai_check_power(struct snd_soc_dapm_widget *w)
903{ 1030{
904 DAPM_UPDATE_STAT(w, power_checks); 1031 DAPM_UPDATE_STAT(w, power_checks);
905 1032
906 return w->active; 1033 if (w->active)
1034 return w->active;
1035
1036 return dapm_generic_check_power(w);
907} 1037}
908 1038
909/* Check to see if an ADC has power */ 1039/* Check to see if an ADC has power */
@@ -914,7 +1044,7 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
914 DAPM_UPDATE_STAT(w, power_checks); 1044 DAPM_UPDATE_STAT(w, power_checks);
915 1045
916 if (w->active) { 1046 if (w->active) {
917 in = is_connected_input_ep(w); 1047 in = is_connected_input_ep(w, NULL);
918 dapm_clear_walk(w->dapm); 1048 dapm_clear_walk(w->dapm);
919 return in != 0; 1049 return in != 0;
920 } else { 1050 } else {
@@ -930,7 +1060,7 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
930 DAPM_UPDATE_STAT(w, power_checks); 1060 DAPM_UPDATE_STAT(w, power_checks);
931 1061
932 if (w->active) { 1062 if (w->active) {
933 out = is_connected_output_ep(w); 1063 out = is_connected_output_ep(w, NULL);
934 dapm_clear_walk(w->dapm); 1064 dapm_clear_walk(w->dapm);
935 return out != 0; 1065 return out != 0;
936 } else { 1066 } else {
@@ -1107,7 +1237,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
1107 "pop test : Applying 0x%x/0x%x to %x in %dms\n", 1237 "pop test : Applying 0x%x/0x%x to %x in %dms\n",
1108 value, mask, reg, card->pop_time); 1238 value, mask, reg, card->pop_time);
1109 pop_wait(card->pop_time); 1239 pop_wait(card->pop_time);
1110 soc_widget_update_bits(w, reg, mask, value); 1240 soc_widget_update_bits_locked(w, reg, mask, value);
1111 } 1241 }
1112 1242
1113 list_for_each_entry(w, pending, power_list) { 1243 list_for_each_entry(w, pending, power_list) {
@@ -1237,7 +1367,7 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
1237 w->name, ret); 1367 w->name, ret);
1238 } 1368 }
1239 1369
1240 ret = snd_soc_update_bits(w->codec, update->reg, update->mask, 1370 ret = soc_widget_update_bits_locked(w, update->reg, update->mask,
1241 update->val); 1371 update->val);
1242 if (ret < 0) 1372 if (ret < 0)
1243 pr_err("%s DAPM update failed: %d\n", w->name, ret); 1373 pr_err("%s DAPM update failed: %d\n", w->name, ret);
@@ -1421,12 +1551,10 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1421 trace_snd_soc_dapm_start(card); 1551 trace_snd_soc_dapm_start(card);
1422 1552
1423 list_for_each_entry(d, &card->dapm_list, list) { 1553 list_for_each_entry(d, &card->dapm_list, list) {
1424 if (d->n_widgets || d->codec == NULL) { 1554 if (d->idle_bias_off)
1425 if (d->idle_bias_off) 1555 d->target_bias_level = SND_SOC_BIAS_OFF;
1426 d->target_bias_level = SND_SOC_BIAS_OFF; 1556 else
1427 else 1557 d->target_bias_level = SND_SOC_BIAS_STANDBY;
1428 d->target_bias_level = SND_SOC_BIAS_STANDBY;
1429 }
1430 } 1558 }
1431 1559
1432 dapm_reset(card); 1560 dapm_reset(card);
@@ -1471,32 +1599,6 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1471 1599
1472 } 1600 }
1473 1601
1474 /* If there are no DAPM widgets then try to figure out power from the
1475 * event type.
1476 */
1477 if (!dapm->n_widgets) {
1478 switch (event) {
1479 case SND_SOC_DAPM_STREAM_START:
1480 case SND_SOC_DAPM_STREAM_RESUME:
1481 dapm->target_bias_level = SND_SOC_BIAS_ON;
1482 break;
1483 case SND_SOC_DAPM_STREAM_STOP:
1484 if (dapm->codec && dapm->codec->active)
1485 dapm->target_bias_level = SND_SOC_BIAS_ON;
1486 else
1487 dapm->target_bias_level = SND_SOC_BIAS_STANDBY;
1488 break;
1489 case SND_SOC_DAPM_STREAM_SUSPEND:
1490 dapm->target_bias_level = SND_SOC_BIAS_STANDBY;
1491 break;
1492 case SND_SOC_DAPM_STREAM_NOP:
1493 dapm->target_bias_level = dapm->bias_level;
1494 break;
1495 default:
1496 break;
1497 }
1498 }
1499
1500 /* Force all contexts in the card to the same bias state if 1602 /* Force all contexts in the card to the same bias state if
1501 * they're not ground referenced. 1603 * they're not ground referenced.
1502 */ 1604 */
@@ -1546,12 +1648,6 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1546} 1648}
1547 1649
1548#ifdef CONFIG_DEBUG_FS 1650#ifdef CONFIG_DEBUG_FS
1549static int dapm_widget_power_open_file(struct inode *inode, struct file *file)
1550{
1551 file->private_data = inode->i_private;
1552 return 0;
1553}
1554
1555static ssize_t dapm_widget_power_read_file(struct file *file, 1651static ssize_t dapm_widget_power_read_file(struct file *file,
1556 char __user *user_buf, 1652 char __user *user_buf,
1557 size_t count, loff_t *ppos) 1653 size_t count, loff_t *ppos)
@@ -1566,9 +1662,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1566 if (!buf) 1662 if (!buf)
1567 return -ENOMEM; 1663 return -ENOMEM;
1568 1664
1569 in = is_connected_input_ep(w); 1665 in = is_connected_input_ep(w, NULL);
1570 dapm_clear_walk(w->dapm); 1666 dapm_clear_walk(w->dapm);
1571 out = is_connected_output_ep(w); 1667 out = is_connected_output_ep(w, NULL);
1572 dapm_clear_walk(w->dapm); 1668 dapm_clear_walk(w->dapm);
1573 1669
1574 ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d", 1670 ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
@@ -1615,17 +1711,11 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1615} 1711}
1616 1712
1617static const struct file_operations dapm_widget_power_fops = { 1713static const struct file_operations dapm_widget_power_fops = {
1618 .open = dapm_widget_power_open_file, 1714 .open = simple_open,
1619 .read = dapm_widget_power_read_file, 1715 .read = dapm_widget_power_read_file,
1620 .llseek = default_llseek, 1716 .llseek = default_llseek,
1621}; 1717};
1622 1718
1623static int dapm_bias_open_file(struct inode *inode, struct file *file)
1624{
1625 file->private_data = inode->i_private;
1626 return 0;
1627}
1628
1629static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf, 1719static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,
1630 size_t count, loff_t *ppos) 1720 size_t count, loff_t *ppos)
1631{ 1721{
@@ -1656,7 +1746,7 @@ static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,
1656} 1746}
1657 1747
1658static const struct file_operations dapm_bias_fops = { 1748static const struct file_operations dapm_bias_fops = {
1659 .open = dapm_bias_open_file, 1749 .open = simple_open,
1660 .read = dapm_bias_read_file, 1750 .read = dapm_bias_read_file,
1661 .llseek = default_llseek, 1751 .llseek = default_llseek,
1662}; 1752};
@@ -1721,7 +1811,7 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
1721#endif 1811#endif
1722 1812
1723/* test and update the power status of a mux widget */ 1813/* test and update the power status of a mux widget */
1724int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 1814static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1725 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) 1815 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
1726{ 1816{
1727 struct snd_soc_dapm_path *path; 1817 struct snd_soc_dapm_path *path;
@@ -1758,12 +1848,26 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1758 dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); 1848 dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
1759 } 1849 }
1760 1850
1761 return 0; 1851 return found;
1852}
1853
1854int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1855 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
1856{
1857 struct snd_soc_card *card = widget->dapm->card;
1858 int ret;
1859
1860 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
1861 ret = soc_dapm_mux_update_power(widget, kcontrol, mux, e);
1862 mutex_unlock(&card->dapm_mutex);
1863 if (ret > 0)
1864 soc_dpcm_runtime_update(widget);
1865 return ret;
1762} 1866}
1763EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power); 1867EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
1764 1868
1765/* test and update the power status of a mixer or switch widget */ 1869/* test and update the power status of a mixer or switch widget */
1766int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 1870static int soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1767 struct snd_kcontrol *kcontrol, int connect) 1871 struct snd_kcontrol *kcontrol, int connect)
1768{ 1872{
1769 struct snd_soc_dapm_path *path; 1873 struct snd_soc_dapm_path *path;
@@ -1790,7 +1894,21 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1790 dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); 1894 dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
1791 } 1895 }
1792 1896
1793 return 0; 1897 return found;
1898}
1899
1900int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1901 struct snd_kcontrol *kcontrol, int connect)
1902{
1903 struct snd_soc_card *card = widget->dapm->card;
1904 int ret;
1905
1906 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
1907 ret = soc_dapm_mixer_update_power(widget, kcontrol, connect);
1908 mutex_unlock(&card->dapm_mutex);
1909 if (ret > 0)
1910 soc_dpcm_runtime_update(widget);
1911 return ret;
1794} 1912}
1795EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); 1913EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
1796 1914
@@ -1951,6 +2069,8 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
1951 */ 2069 */
1952int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) 2070int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
1953{ 2071{
2072 int ret;
2073
1954 /* 2074 /*
1955 * Suppress early reports (eg, jacks syncing their state) to avoid 2075 * Suppress early reports (eg, jacks syncing their state) to avoid
1956 * silly DAPM runs during card startup. 2076 * silly DAPM runs during card startup.
@@ -1958,7 +2078,10 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
1958 if (!dapm->card || !dapm->card->instantiated) 2078 if (!dapm->card || !dapm->card->instantiated)
1959 return 0; 2079 return 0;
1960 2080
1961 return dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); 2081 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2082 ret = dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
2083 mutex_unlock(&dapm->card->dapm_mutex);
2084 return ret;
1962} 2085}
1963EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); 2086EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
1964 2087
@@ -2067,6 +2190,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2067 case snd_soc_dapm_aif_in: 2190 case snd_soc_dapm_aif_in:
2068 case snd_soc_dapm_aif_out: 2191 case snd_soc_dapm_aif_out:
2069 case snd_soc_dapm_dai: 2192 case snd_soc_dapm_dai:
2193 case snd_soc_dapm_dai_link:
2070 list_add(&path->list, &dapm->card->paths); 2194 list_add(&path->list, &dapm->card->paths);
2071 list_add(&path->list_sink, &wsink->sources); 2195 list_add(&path->list_sink, &wsink->sources);
2072 list_add(&path->list_source, &wsource->sinks); 2196 list_add(&path->list_source, &wsource->sinks);
@@ -2122,19 +2246,21 @@ err:
2122int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, 2246int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
2123 const struct snd_soc_dapm_route *route, int num) 2247 const struct snd_soc_dapm_route *route, int num)
2124{ 2248{
2125 int i, ret; 2249 int i, ret = 0;
2126 2250
2251 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2127 for (i = 0; i < num; i++) { 2252 for (i = 0; i < num; i++) {
2128 ret = snd_soc_dapm_add_route(dapm, route); 2253 ret = snd_soc_dapm_add_route(dapm, route);
2129 if (ret < 0) { 2254 if (ret < 0) {
2130 dev_err(dapm->dev, "Failed to add route %s->%s\n", 2255 dev_err(dapm->dev, "Failed to add route %s->%s\n",
2131 route->source, route->sink); 2256 route->source, route->sink);
2132 return ret; 2257 break;
2133 } 2258 }
2134 route++; 2259 route++;
2135 } 2260 }
2261 mutex_unlock(&dapm->card->dapm_mutex);
2136 2262
2137 return 0; 2263 return ret;
2138} 2264}
2139EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); 2265EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
2140 2266
@@ -2205,12 +2331,14 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
2205 int i, err; 2331 int i, err;
2206 int ret = 0; 2332 int ret = 0;
2207 2333
2334 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2208 for (i = 0; i < num; i++) { 2335 for (i = 0; i < num; i++) {
2209 err = snd_soc_dapm_weak_route(dapm, route); 2336 err = snd_soc_dapm_weak_route(dapm, route);
2210 if (err) 2337 if (err)
2211 ret = err; 2338 ret = err;
2212 route++; 2339 route++;
2213 } 2340 }
2341 mutex_unlock(&dapm->card->dapm_mutex);
2214 2342
2215 return ret; 2343 return ret;
2216} 2344}
@@ -2229,6 +2357,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2229 struct snd_soc_dapm_widget *w; 2357 struct snd_soc_dapm_widget *w;
2230 unsigned int val; 2358 unsigned int val;
2231 2359
2360 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2361
2232 list_for_each_entry(w, &dapm->card->widgets, list) 2362 list_for_each_entry(w, &dapm->card->widgets, list)
2233 { 2363 {
2234 if (w->new) 2364 if (w->new)
@@ -2238,8 +2368,10 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2238 w->kcontrols = kzalloc(w->num_kcontrols * 2368 w->kcontrols = kzalloc(w->num_kcontrols *
2239 sizeof(struct snd_kcontrol *), 2369 sizeof(struct snd_kcontrol *),
2240 GFP_KERNEL); 2370 GFP_KERNEL);
2241 if (!w->kcontrols) 2371 if (!w->kcontrols) {
2372 mutex_unlock(&dapm->card->dapm_mutex);
2242 return -ENOMEM; 2373 return -ENOMEM;
2374 }
2243 } 2375 }
2244 2376
2245 switch(w->id) { 2377 switch(w->id) {
@@ -2279,6 +2411,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2279 } 2411 }
2280 2412
2281 dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); 2413 dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
2414 mutex_unlock(&dapm->card->dapm_mutex);
2282 return 0; 2415 return 0;
2283} 2416}
2284EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); 2417EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
@@ -2338,6 +2471,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2338 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2471 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2339 struct snd_soc_dapm_widget *widget = wlist->widgets[0]; 2472 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2340 struct snd_soc_codec *codec = widget->codec; 2473 struct snd_soc_codec *codec = widget->codec;
2474 struct snd_soc_card *card = codec->card;
2341 struct soc_mixer_control *mc = 2475 struct soc_mixer_control *mc =
2342 (struct soc_mixer_control *)kcontrol->private_value; 2476 (struct soc_mixer_control *)kcontrol->private_value;
2343 unsigned int reg = mc->reg; 2477 unsigned int reg = mc->reg;
@@ -2364,7 +2498,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2364 /* old connection must be powered down */ 2498 /* old connection must be powered down */
2365 connect = invert ? 1 : 0; 2499 connect = invert ? 1 : 0;
2366 2500
2367 mutex_lock(&codec->mutex); 2501 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2368 2502
2369 change = snd_soc_test_bits(widget->codec, reg, mask, val); 2503 change = snd_soc_test_bits(widget->codec, reg, mask, val);
2370 if (change) { 2504 if (change) {
@@ -2380,13 +2514,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2380 update.val = val; 2514 update.val = val;
2381 widget->dapm->update = &update; 2515 widget->dapm->update = &update;
2382 2516
2383 snd_soc_dapm_mixer_update_power(widget, kcontrol, connect); 2517 soc_dapm_mixer_update_power(widget, kcontrol, connect);
2384 2518
2385 widget->dapm->update = NULL; 2519 widget->dapm->update = NULL;
2386 } 2520 }
2387 } 2521 }
2388 2522
2389 mutex_unlock(&codec->mutex); 2523 mutex_unlock(&card->dapm_mutex);
2390 return 0; 2524 return 0;
2391} 2525}
2392EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); 2526EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
@@ -2435,6 +2569,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2435 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2569 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2436 struct snd_soc_dapm_widget *widget = wlist->widgets[0]; 2570 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2437 struct snd_soc_codec *codec = widget->codec; 2571 struct snd_soc_codec *codec = widget->codec;
2572 struct snd_soc_card *card = codec->card;
2438 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2573 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2439 unsigned int val, mux, change; 2574 unsigned int val, mux, change;
2440 unsigned int mask, bitmask; 2575 unsigned int mask, bitmask;
@@ -2455,7 +2590,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2455 mask |= (bitmask - 1) << e->shift_r; 2590 mask |= (bitmask - 1) << e->shift_r;
2456 } 2591 }
2457 2592
2458 mutex_lock(&codec->mutex); 2593 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2459 2594
2460 change = snd_soc_test_bits(widget->codec, e->reg, mask, val); 2595 change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
2461 if (change) { 2596 if (change) {
@@ -2471,13 +2606,13 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2471 update.val = val; 2606 update.val = val;
2472 widget->dapm->update = &update; 2607 widget->dapm->update = &update;
2473 2608
2474 snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e); 2609 soc_dapm_mux_update_power(widget, kcontrol, mux, e);
2475 2610
2476 widget->dapm->update = NULL; 2611 widget->dapm->update = NULL;
2477 } 2612 }
2478 } 2613 }
2479 2614
2480 mutex_unlock(&codec->mutex); 2615 mutex_unlock(&card->dapm_mutex);
2481 return change; 2616 return change;
2482} 2617}
2483EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); 2618EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
@@ -2514,6 +2649,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
2514 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2649 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2515 struct snd_soc_dapm_widget *widget = wlist->widgets[0]; 2650 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2516 struct snd_soc_codec *codec = widget->codec; 2651 struct snd_soc_codec *codec = widget->codec;
2652 struct snd_soc_card *card = codec->card;
2517 struct soc_enum *e = 2653 struct soc_enum *e =
2518 (struct soc_enum *)kcontrol->private_value; 2654 (struct soc_enum *)kcontrol->private_value;
2519 int change; 2655 int change;
@@ -2523,7 +2659,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
2523 if (ucontrol->value.enumerated.item[0] >= e->max) 2659 if (ucontrol->value.enumerated.item[0] >= e->max)
2524 return -EINVAL; 2660 return -EINVAL;
2525 2661
2526 mutex_lock(&codec->mutex); 2662 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2527 2663
2528 change = widget->value != ucontrol->value.enumerated.item[0]; 2664 change = widget->value != ucontrol->value.enumerated.item[0];
2529 if (change) { 2665 if (change) {
@@ -2532,11 +2668,11 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
2532 2668
2533 widget->value = ucontrol->value.enumerated.item[0]; 2669 widget->value = ucontrol->value.enumerated.item[0];
2534 2670
2535 snd_soc_dapm_mux_update_power(widget, kcontrol, widget->value, e); 2671 soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
2536 } 2672 }
2537 } 2673 }
2538 2674
2539 mutex_unlock(&codec->mutex); 2675 mutex_unlock(&card->dapm_mutex);
2540 return ret; 2676 return ret;
2541} 2677}
2542EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); 2678EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
@@ -2601,6 +2737,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
2601 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2737 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2602 struct snd_soc_dapm_widget *widget = wlist->widgets[0]; 2738 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2603 struct snd_soc_codec *codec = widget->codec; 2739 struct snd_soc_codec *codec = widget->codec;
2740 struct snd_soc_card *card = codec->card;
2604 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2741 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2605 unsigned int val, mux, change; 2742 unsigned int val, mux, change;
2606 unsigned int mask; 2743 unsigned int mask;
@@ -2619,7 +2756,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
2619 mask |= e->mask << e->shift_r; 2756 mask |= e->mask << e->shift_r;
2620 } 2757 }
2621 2758
2622 mutex_lock(&codec->mutex); 2759 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2623 2760
2624 change = snd_soc_test_bits(widget->codec, e->reg, mask, val); 2761 change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
2625 if (change) { 2762 if (change) {
@@ -2635,13 +2772,13 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
2635 update.val = val; 2772 update.val = val;
2636 widget->dapm->update = &update; 2773 widget->dapm->update = &update;
2637 2774
2638 snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e); 2775 soc_dapm_mux_update_power(widget, kcontrol, mux, e);
2639 2776
2640 widget->dapm->update = NULL; 2777 widget->dapm->update = NULL;
2641 } 2778 }
2642 } 2779 }
2643 2780
2644 mutex_unlock(&codec->mutex); 2781 mutex_unlock(&card->dapm_mutex);
2645 return change; 2782 return change;
2646} 2783}
2647EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); 2784EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
@@ -2678,12 +2815,12 @@ int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
2678 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); 2815 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
2679 const char *pin = (const char *)kcontrol->private_value; 2816 const char *pin = (const char *)kcontrol->private_value;
2680 2817
2681 mutex_lock(&card->mutex); 2818 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2682 2819
2683 ucontrol->value.integer.value[0] = 2820 ucontrol->value.integer.value[0] =
2684 snd_soc_dapm_get_pin_status(&card->dapm, pin); 2821 snd_soc_dapm_get_pin_status(&card->dapm, pin);
2685 2822
2686 mutex_unlock(&card->mutex); 2823 mutex_unlock(&card->dapm_mutex);
2687 2824
2688 return 0; 2825 return 0;
2689} 2826}
@@ -2701,17 +2838,16 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
2701 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); 2838 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
2702 const char *pin = (const char *)kcontrol->private_value; 2839 const char *pin = (const char *)kcontrol->private_value;
2703 2840
2704 mutex_lock(&card->mutex); 2841 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2705 2842
2706 if (ucontrol->value.integer.value[0]) 2843 if (ucontrol->value.integer.value[0])
2707 snd_soc_dapm_enable_pin(&card->dapm, pin); 2844 snd_soc_dapm_enable_pin(&card->dapm, pin);
2708 else 2845 else
2709 snd_soc_dapm_disable_pin(&card->dapm, pin); 2846 snd_soc_dapm_disable_pin(&card->dapm, pin);
2710 2847
2711 snd_soc_dapm_sync(&card->dapm); 2848 mutex_unlock(&card->dapm_mutex);
2712
2713 mutex_unlock(&card->mutex);
2714 2849
2850 snd_soc_dapm_sync(&card->dapm);
2715 return 0; 2851 return 0;
2716} 2852}
2717EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); 2853EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
@@ -2729,9 +2865,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2729 2865
2730 switch (w->id) { 2866 switch (w->id) {
2731 case snd_soc_dapm_regulator_supply: 2867 case snd_soc_dapm_regulator_supply:
2732 w->priv = devm_regulator_get(dapm->dev, w->name); 2868 w->regulator = devm_regulator_get(dapm->dev, w->name);
2733 if (IS_ERR(w->priv)) { 2869 if (IS_ERR(w->regulator)) {
2734 ret = PTR_ERR(w->priv); 2870 ret = PTR_ERR(w->regulator);
2735 dev_err(dapm->dev, "Failed to request %s: %d\n", 2871 dev_err(dapm->dev, "Failed to request %s: %d\n",
2736 w->name, ret); 2872 w->name, ret);
2737 return NULL; 2873 return NULL;
@@ -2783,6 +2919,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2783 case snd_soc_dapm_hp: 2919 case snd_soc_dapm_hp:
2784 case snd_soc_dapm_mic: 2920 case snd_soc_dapm_mic:
2785 case snd_soc_dapm_line: 2921 case snd_soc_dapm_line:
2922 case snd_soc_dapm_dai_link:
2786 w->power_check = dapm_generic_check_power; 2923 w->power_check = dapm_generic_check_power;
2787 break; 2924 break;
2788 case snd_soc_dapm_supply: 2925 case snd_soc_dapm_supply:
@@ -2828,21 +2965,177 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
2828{ 2965{
2829 struct snd_soc_dapm_widget *w; 2966 struct snd_soc_dapm_widget *w;
2830 int i; 2967 int i;
2968 int ret = 0;
2831 2969
2970 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2832 for (i = 0; i < num; i++) { 2971 for (i = 0; i < num; i++) {
2833 w = snd_soc_dapm_new_control(dapm, widget); 2972 w = snd_soc_dapm_new_control(dapm, widget);
2834 if (!w) { 2973 if (!w) {
2835 dev_err(dapm->dev, 2974 dev_err(dapm->dev,
2836 "ASoC: Failed to create DAPM control %s\n", 2975 "ASoC: Failed to create DAPM control %s\n",
2837 widget->name); 2976 widget->name);
2838 return -ENOMEM; 2977 ret = -ENOMEM;
2978 break;
2839 } 2979 }
2840 widget++; 2980 widget++;
2841 } 2981 }
2842 return 0; 2982 mutex_unlock(&dapm->card->dapm_mutex);
2983 return ret;
2843} 2984}
2844EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); 2985EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
2845 2986
2987static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
2988 struct snd_kcontrol *kcontrol, int event)
2989{
2990 struct snd_soc_dapm_path *source_p, *sink_p;
2991 struct snd_soc_dai *source, *sink;
2992 const struct snd_soc_pcm_stream *config = w->params;
2993 struct snd_pcm_substream substream;
2994 struct snd_pcm_hw_params *params = NULL;
2995 u64 fmt;
2996 int ret;
2997
2998 BUG_ON(!config);
2999 BUG_ON(list_empty(&w->sources) || list_empty(&w->sinks));
3000
3001 /* We only support a single source and sink, pick the first */
3002 source_p = list_first_entry(&w->sources, struct snd_soc_dapm_path,
3003 list_sink);
3004 sink_p = list_first_entry(&w->sinks, struct snd_soc_dapm_path,
3005 list_source);
3006
3007 BUG_ON(!source_p || !sink_p);
3008 BUG_ON(!sink_p->source || !source_p->sink);
3009 BUG_ON(!source_p->source || !sink_p->sink);
3010
3011 source = source_p->source->priv;
3012 sink = sink_p->sink->priv;
3013
3014 /* Be a little careful as we don't want to overflow the mask array */
3015 if (config->formats) {
3016 fmt = ffs(config->formats) - 1;
3017 } else {
3018 dev_warn(w->dapm->dev, "Invalid format %llx specified\n",
3019 config->formats);
3020 fmt = 0;
3021 }
3022
3023 /* Currently very limited parameter selection */
3024 params = kzalloc(sizeof(*params), GFP_KERNEL);
3025 if (!params) {
3026 ret = -ENOMEM;
3027 goto out;
3028 }
3029 snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt);
3030
3031 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min =
3032 config->rate_min;
3033 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max =
3034 config->rate_max;
3035
3036 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min
3037 = config->channels_min;
3038 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max
3039 = config->channels_max;
3040
3041 memset(&substream, 0, sizeof(substream));
3042
3043 switch (event) {
3044 case SND_SOC_DAPM_PRE_PMU:
3045 if (source->driver->ops && source->driver->ops->hw_params) {
3046 substream.stream = SNDRV_PCM_STREAM_CAPTURE;
3047 ret = source->driver->ops->hw_params(&substream,
3048 params, source);
3049 if (ret != 0) {
3050 dev_err(source->dev,
3051 "hw_params() failed: %d\n", ret);
3052 goto out;
3053 }
3054 }
3055
3056 if (sink->driver->ops && sink->driver->ops->hw_params) {
3057 substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
3058 ret = sink->driver->ops->hw_params(&substream, params,
3059 sink);
3060 if (ret != 0) {
3061 dev_err(sink->dev,
3062 "hw_params() failed: %d\n", ret);
3063 goto out;
3064 }
3065 }
3066 break;
3067
3068 case SND_SOC_DAPM_POST_PMU:
3069 ret = snd_soc_dai_digital_mute(sink, 0);
3070 if (ret != 0 && ret != -ENOTSUPP)
3071 dev_warn(sink->dev, "Failed to unmute: %d\n", ret);
3072 ret = 0;
3073 break;
3074
3075 case SND_SOC_DAPM_PRE_PMD:
3076 ret = snd_soc_dai_digital_mute(sink, 1);
3077 if (ret != 0 && ret != -ENOTSUPP)
3078 dev_warn(sink->dev, "Failed to mute: %d\n", ret);
3079 ret = 0;
3080 break;
3081
3082 default:
3083 BUG();
3084 return -EINVAL;
3085 }
3086
3087out:
3088 kfree(params);
3089 return ret;
3090}
3091
3092int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
3093 const struct snd_soc_pcm_stream *params,
3094 struct snd_soc_dapm_widget *source,
3095 struct snd_soc_dapm_widget *sink)
3096{
3097 struct snd_soc_dapm_route routes[2];
3098 struct snd_soc_dapm_widget template;
3099 struct snd_soc_dapm_widget *w;
3100 size_t len;
3101 char *link_name;
3102
3103 len = strlen(source->name) + strlen(sink->name) + 2;
3104 link_name = devm_kzalloc(card->dev, len, GFP_KERNEL);
3105 if (!link_name)
3106 return -ENOMEM;
3107 snprintf(link_name, len, "%s-%s", source->name, sink->name);
3108
3109 memset(&template, 0, sizeof(template));
3110 template.reg = SND_SOC_NOPM;
3111 template.id = snd_soc_dapm_dai_link;
3112 template.name = link_name;
3113 template.event = snd_soc_dai_link_event;
3114 template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
3115 SND_SOC_DAPM_PRE_PMD;
3116
3117 dev_dbg(card->dev, "adding %s widget\n", link_name);
3118
3119 w = snd_soc_dapm_new_control(&card->dapm, &template);
3120 if (!w) {
3121 dev_err(card->dev, "Failed to create %s widget\n",
3122 link_name);
3123 return -ENOMEM;
3124 }
3125
3126 w->params = params;
3127
3128 memset(&routes, 0, sizeof(routes));
3129
3130 routes[0].source = source->name;
3131 routes[0].sink = link_name;
3132 routes[1].source = link_name;
3133 routes[1].sink = sink->name;
3134
3135 return snd_soc_dapm_add_routes(&card->dapm, routes,
3136 ARRAY_SIZE(routes));
3137}
3138
2846int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, 3139int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
2847 struct snd_soc_dai *dai) 3140 struct snd_soc_dai *dai)
2848{ 3141{
@@ -2946,37 +3239,61 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
2946 return 0; 3239 return 0;
2947} 3240}
2948 3241
2949static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm, 3242static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
2950 int stream, struct snd_soc_dai *dai, 3243 int event)
2951 int event)
2952{ 3244{
2953 struct snd_soc_dapm_widget *w;
2954 3245
2955 if (stream == SNDRV_PCM_STREAM_PLAYBACK) 3246 struct snd_soc_dapm_widget *w_cpu, *w_codec;
2956 w = dai->playback_widget; 3247 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
2957 else 3248 struct snd_soc_dai *codec_dai = rtd->codec_dai;
2958 w = dai->capture_widget;
2959 3249
2960 if (!w) 3250 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2961 return; 3251 w_cpu = cpu_dai->playback_widget;
3252 w_codec = codec_dai->playback_widget;
3253 } else {
3254 w_cpu = cpu_dai->capture_widget;
3255 w_codec = codec_dai->capture_widget;
3256 }
2962 3257
2963 dapm_mark_dirty(w, "stream event"); 3258 if (w_cpu) {
2964 3259
2965 switch (event) { 3260 dapm_mark_dirty(w_cpu, "stream event");
2966 case SND_SOC_DAPM_STREAM_START: 3261
2967 w->active = 1; 3262 switch (event) {
2968 break; 3263 case SND_SOC_DAPM_STREAM_START:
2969 case SND_SOC_DAPM_STREAM_STOP: 3264 w_cpu->active = 1;
2970 w->active = 0; 3265 break;
2971 break; 3266 case SND_SOC_DAPM_STREAM_STOP:
2972 case SND_SOC_DAPM_STREAM_SUSPEND: 3267 w_cpu->active = 0;
2973 case SND_SOC_DAPM_STREAM_RESUME: 3268 break;
2974 case SND_SOC_DAPM_STREAM_PAUSE_PUSH: 3269 case SND_SOC_DAPM_STREAM_SUSPEND:
2975 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: 3270 case SND_SOC_DAPM_STREAM_RESUME:
2976 break; 3271 case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
3272 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
3273 break;
3274 }
2977 } 3275 }
2978 3276
2979 dapm_power_widgets(dapm, event); 3277 if (w_codec) {
3278
3279 dapm_mark_dirty(w_codec, "stream event");
3280
3281 switch (event) {
3282 case SND_SOC_DAPM_STREAM_START:
3283 w_codec->active = 1;
3284 break;
3285 case SND_SOC_DAPM_STREAM_STOP:
3286 w_codec->active = 0;
3287 break;
3288 case SND_SOC_DAPM_STREAM_SUSPEND:
3289 case SND_SOC_DAPM_STREAM_RESUME:
3290 case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
3291 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
3292 break;
3293 }
3294 }
3295
3296 dapm_power_widgets(&rtd->card->dapm, event);
2980} 3297}
2981 3298
2982/** 3299/**
@@ -2990,15 +3307,14 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
2990 * 3307 *
2991 * Returns 0 for success else error. 3308 * Returns 0 for success else error.
2992 */ 3309 */
2993int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, 3310void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
2994 struct snd_soc_dai *dai, int event) 3311 int event)
2995{ 3312{
2996 struct snd_soc_codec *codec = rtd->codec; 3313 struct snd_soc_card *card = rtd->card;
2997 3314
2998 mutex_lock(&codec->mutex); 3315 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2999 soc_dapm_stream_event(&codec->dapm, stream, dai, event); 3316 soc_dapm_stream_event(rtd, stream, event);
3000 mutex_unlock(&codec->mutex); 3317 mutex_unlock(&card->dapm_mutex);
3001 return 0;
3002} 3318}
3003 3319
3004/** 3320/**