diff options
author | Mark Brown <broonie@kernel.org> | 2014-12-08 08:11:44 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-12-08 08:11:44 -0500 |
commit | 941725f5fade7b35394f497c4d684d64a0e05965 (patch) | |
tree | f18b21c23255446f4ae8e5783b2637af9b6fb98f | |
parent | 3ee3f454632547a8299c16156c3fefcc2a05726c (diff) | |
parent | c362effe5cda4df02aa7670d58636ea73979e304 (diff) |
Merge remote-tracking branch 'asoc/topic/core' into asoc-next
-rw-r--r-- | include/sound/soc-dai.h | 3 | ||||
-rw-r--r-- | include/sound/soc-dapm.h | 9 | ||||
-rw-r--r-- | include/sound/soc.h | 29 | ||||
-rw-r--r-- | sound/soc/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 1079 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 755 | ||||
-rw-r--r-- | sound/soc/soc-ops.c | 952 | ||||
-rw-r--r-- | sound/soc/soc-pcm.c | 3 | ||||
-rw-r--r-- | sound/soc/txx9/txx9aclc.c | 2 |
9 files changed, 1388 insertions, 1446 deletions
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index e8b3080d196a..373d1775ecba 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h | |||
@@ -268,7 +268,6 @@ struct snd_soc_dai { | |||
268 | unsigned int sample_bits; | 268 | unsigned int sample_bits; |
269 | 269 | ||
270 | /* parent platform/codec */ | 270 | /* parent platform/codec */ |
271 | struct snd_soc_platform *platform; | ||
272 | struct snd_soc_codec *codec; | 271 | struct snd_soc_codec *codec; |
273 | struct snd_soc_component *component; | 272 | struct snd_soc_component *component; |
274 | 273 | ||
@@ -276,8 +275,6 @@ struct snd_soc_dai { | |||
276 | unsigned int tx_mask; | 275 | unsigned int tx_mask; |
277 | unsigned int rx_mask; | 276 | unsigned int rx_mask; |
278 | 277 | ||
279 | struct snd_soc_card *card; | ||
280 | |||
281 | struct list_head list; | 278 | struct list_head list; |
282 | }; | 279 | }; |
283 | 280 | ||
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 3a4d7da67b8d..89823cfe6f04 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -435,7 +435,7 @@ void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card); | |||
435 | unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol); | 435 | unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol); |
436 | 436 | ||
437 | /* Mostly internal - should not normally be used */ | 437 | /* Mostly internal - should not normally be used */ |
438 | void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm); | 438 | void dapm_mark_endpoints_dirty(struct snd_soc_card *card); |
439 | 439 | ||
440 | /* dapm path query */ | 440 | /* dapm path query */ |
441 | int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, | 441 | int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, |
@@ -508,9 +508,9 @@ struct snd_soc_dapm_path { | |||
508 | 508 | ||
509 | /* status */ | 509 | /* status */ |
510 | u32 connect:1; /* source and sink widgets are connected */ | 510 | u32 connect:1; /* source and sink widgets are connected */ |
511 | u32 walked:1; /* path has been walked */ | ||
512 | u32 walking:1; /* path is in the process of being walked */ | 511 | u32 walking:1; /* path is in the process of being walked */ |
513 | u32 weak:1; /* path ignored for power management */ | 512 | u32 weak:1; /* path ignored for power management */ |
513 | u32 is_supply:1; /* At least one of the connected widgets is a supply */ | ||
514 | 514 | ||
515 | int (*connected)(struct snd_soc_dapm_widget *source, | 515 | int (*connected)(struct snd_soc_dapm_widget *source, |
516 | struct snd_soc_dapm_widget *sink); | 516 | struct snd_soc_dapm_widget *sink); |
@@ -544,11 +544,13 @@ struct snd_soc_dapm_widget { | |||
544 | unsigned char active:1; /* active stream on DAC, ADC's */ | 544 | unsigned char active:1; /* active stream on DAC, ADC's */ |
545 | unsigned char connected:1; /* connected codec pin */ | 545 | unsigned char connected:1; /* connected codec pin */ |
546 | unsigned char new:1; /* cnew complete */ | 546 | unsigned char new:1; /* cnew complete */ |
547 | unsigned char ext:1; /* has external widgets */ | ||
548 | unsigned char force:1; /* force state */ | 547 | unsigned char force:1; /* force state */ |
549 | unsigned char ignore_suspend:1; /* kept enabled over suspend */ | 548 | unsigned char ignore_suspend:1; /* kept enabled over suspend */ |
550 | unsigned char new_power:1; /* power from this run */ | 549 | unsigned char new_power:1; /* power from this run */ |
551 | unsigned char power_checked:1; /* power checked this run */ | 550 | unsigned char power_checked:1; /* power checked this run */ |
551 | unsigned char is_supply:1; /* Widget is a supply type widget */ | ||
552 | unsigned char is_sink:1; /* Widget is a sink type widget */ | ||
553 | unsigned char is_source:1; /* Widget is a source type widget */ | ||
552 | int subseq; /* sort within widget type */ | 554 | int subseq; /* sort within widget type */ |
553 | 555 | ||
554 | int (*power_check)(struct snd_soc_dapm_widget *w); | 556 | int (*power_check)(struct snd_soc_dapm_widget *w); |
@@ -567,6 +569,7 @@ struct snd_soc_dapm_widget { | |||
567 | struct list_head sinks; | 569 | struct list_head sinks; |
568 | 570 | ||
569 | /* used during DAPM updates */ | 571 | /* used during DAPM updates */ |
572 | struct list_head work_list; | ||
570 | struct list_head power_list; | 573 | struct list_head power_list; |
571 | struct list_head dirty; | 574 | struct list_head dirty; |
572 | int inputs; | 575 | int inputs; |
diff --git a/include/sound/soc.h b/include/sound/soc.h index fadcb351f3e1..38769cc900c9 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -36,6 +36,11 @@ | |||
36 | {.reg = xreg, .rreg = xreg, .shift = shift_left, \ | 36 | {.reg = xreg, .rreg = xreg, .shift = shift_left, \ |
37 | .rshift = shift_right, .max = xmax, .platform_max = xmax, \ | 37 | .rshift = shift_right, .max = xmax, .platform_max = xmax, \ |
38 | .invert = xinvert, .autodisable = xautodisable}) | 38 | .invert = xinvert, .autodisable = xautodisable}) |
39 | #define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, xinvert, xautodisable) \ | ||
40 | ((unsigned long)&(struct soc_mixer_control) \ | ||
41 | {.reg = xreg, .rreg = xreg, .shift = shift_left, \ | ||
42 | .rshift = shift_right, .min = xmin, .max = xmax, .platform_max = xmax, \ | ||
43 | .sign_bit = xsign_bit, .invert = xinvert, .autodisable = xautodisable}) | ||
39 | #define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \ | 44 | #define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \ |
40 | SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable) | 45 | SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable) |
41 | #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ | 46 | #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ |
@@ -171,11 +176,9 @@ | |||
171 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | 176 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ |
172 | SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | 177 | SNDRV_CTL_ELEM_ACCESS_READWRITE, \ |
173 | .tlv.p = (tlv_array), \ | 178 | .tlv.p = (tlv_array), \ |
174 | .info = snd_soc_info_volsw_s8, .get = snd_soc_get_volsw_s8, \ | 179 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ |
175 | .put = snd_soc_put_volsw_s8, \ | 180 | .put = snd_soc_put_volsw, \ |
176 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | 181 | .private_value = SOC_DOUBLE_S_VALUE(xreg, 0, 8, xmin, xmax, 7, 0, 0) } |
177 | {.reg = xreg, .min = xmin, .max = xmax, \ | ||
178 | .platform_max = xmax} } | ||
179 | #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xitems, xtexts) \ | 182 | #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xitems, xtexts) \ |
180 | { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ | 183 | { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ |
181 | .items = xitems, .texts = xtexts, \ | 184 | .items = xitems, .texts = xtexts, \ |
@@ -541,12 +544,6 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, | |||
541 | struct snd_ctl_elem_value *ucontrol); | 544 | struct snd_ctl_elem_value *ucontrol); |
542 | int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, | 545 | int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, |
543 | struct snd_ctl_elem_value *ucontrol); | 546 | struct snd_ctl_elem_value *ucontrol); |
544 | int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, | ||
545 | struct snd_ctl_elem_info *uinfo); | ||
546 | int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, | ||
547 | struct snd_ctl_elem_value *ucontrol); | ||
548 | int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, | ||
549 | struct snd_ctl_elem_value *ucontrol); | ||
550 | int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, | 547 | int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, |
551 | struct snd_ctl_elem_info *uinfo); | 548 | struct snd_ctl_elem_info *uinfo); |
552 | int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | 549 | int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, |
@@ -854,8 +851,6 @@ struct snd_soc_platform_driver { | |||
854 | 851 | ||
855 | int (*probe)(struct snd_soc_platform *); | 852 | int (*probe)(struct snd_soc_platform *); |
856 | int (*remove)(struct snd_soc_platform *); | 853 | int (*remove)(struct snd_soc_platform *); |
857 | int (*suspend)(struct snd_soc_dai *dai); | ||
858 | int (*resume)(struct snd_soc_dai *dai); | ||
859 | struct snd_soc_component_driver component_driver; | 854 | struct snd_soc_component_driver component_driver; |
860 | 855 | ||
861 | /* pcm creation and destruction */ | 856 | /* pcm creation and destruction */ |
@@ -880,7 +875,7 @@ struct snd_soc_platform_driver { | |||
880 | 875 | ||
881 | struct snd_soc_dai_link_component { | 876 | struct snd_soc_dai_link_component { |
882 | const char *name; | 877 | const char *name; |
883 | const struct device_node *of_node; | 878 | struct device_node *of_node; |
884 | const char *dai_name; | 879 | const char *dai_name; |
885 | }; | 880 | }; |
886 | 881 | ||
@@ -888,8 +883,6 @@ struct snd_soc_platform { | |||
888 | struct device *dev; | 883 | struct device *dev; |
889 | const struct snd_soc_platform_driver *driver; | 884 | const struct snd_soc_platform_driver *driver; |
890 | 885 | ||
891 | unsigned int suspended:1; /* platform is suspended */ | ||
892 | |||
893 | struct list_head list; | 886 | struct list_head list; |
894 | 887 | ||
895 | struct snd_soc_component component; | 888 | struct snd_soc_component component; |
@@ -984,7 +977,7 @@ struct snd_soc_codec_conf { | |||
984 | * DT/OF node, but not both. | 977 | * DT/OF node, but not both. |
985 | */ | 978 | */ |
986 | const char *dev_name; | 979 | const char *dev_name; |
987 | const struct device_node *of_node; | 980 | struct device_node *of_node; |
988 | 981 | ||
989 | /* | 982 | /* |
990 | * optional map of kcontrol, widget and path name prefixes that are | 983 | * optional map of kcontrol, widget and path name prefixes that are |
@@ -1001,7 +994,7 @@ struct snd_soc_aux_dev { | |||
1001 | * DT/OF node, but not both. | 994 | * DT/OF node, but not both. |
1002 | */ | 995 | */ |
1003 | const char *codec_name; | 996 | const char *codec_name; |
1004 | const struct device_node *codec_of_node; | 997 | struct device_node *codec_of_node; |
1005 | 998 | ||
1006 | /* codec/machine specific init - e.g. add machine controls */ | 999 | /* codec/machine specific init - e.g. add machine controls */ |
1007 | int (*init)(struct snd_soc_component *component); | 1000 | int (*init)(struct snd_soc_component *component); |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index d88edfced8c4..2a043804a2bc 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o |
2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o | 2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o soc-ops.o |
3 | 3 | ||
4 | ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) | 4 | ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) |
5 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o | 5 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 78a94fc82446..397d00aee43f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -589,17 +589,12 @@ int snd_soc_suspend(struct device *dev) | |||
589 | 589 | ||
590 | for (i = 0; i < card->num_rtd; i++) { | 590 | for (i = 0; i < card->num_rtd; i++) { |
591 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 591 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
592 | struct snd_soc_platform *platform = card->rtd[i].platform; | ||
593 | 592 | ||
594 | if (card->rtd[i].dai_link->ignore_suspend) | 593 | if (card->rtd[i].dai_link->ignore_suspend) |
595 | continue; | 594 | continue; |
596 | 595 | ||
597 | if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control) | 596 | if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control) |
598 | cpu_dai->driver->suspend(cpu_dai); | 597 | cpu_dai->driver->suspend(cpu_dai); |
599 | if (platform->driver->suspend && !platform->suspended) { | ||
600 | platform->driver->suspend(cpu_dai); | ||
601 | platform->suspended = 1; | ||
602 | } | ||
603 | } | 598 | } |
604 | 599 | ||
605 | /* close any waiting streams and save state */ | 600 | /* close any waiting streams and save state */ |
@@ -626,8 +621,8 @@ int snd_soc_suspend(struct device *dev) | |||
626 | SND_SOC_DAPM_STREAM_SUSPEND); | 621 | SND_SOC_DAPM_STREAM_SUSPEND); |
627 | } | 622 | } |
628 | 623 | ||
629 | /* Recheck all analogue paths too */ | 624 | /* Recheck all endpoints too, their state is affected by suspend */ |
630 | dapm_mark_io_dirty(&card->dapm); | 625 | dapm_mark_endpoints_dirty(card); |
631 | snd_soc_dapm_sync(&card->dapm); | 626 | snd_soc_dapm_sync(&card->dapm); |
632 | 627 | ||
633 | /* suspend all CODECs */ | 628 | /* suspend all CODECs */ |
@@ -771,17 +766,12 @@ static void soc_resume_deferred(struct work_struct *work) | |||
771 | 766 | ||
772 | for (i = 0; i < card->num_rtd; i++) { | 767 | for (i = 0; i < card->num_rtd; i++) { |
773 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 768 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
774 | struct snd_soc_platform *platform = card->rtd[i].platform; | ||
775 | 769 | ||
776 | if (card->rtd[i].dai_link->ignore_suspend) | 770 | if (card->rtd[i].dai_link->ignore_suspend) |
777 | continue; | 771 | continue; |
778 | 772 | ||
779 | if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control) | 773 | if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control) |
780 | cpu_dai->driver->resume(cpu_dai); | 774 | cpu_dai->driver->resume(cpu_dai); |
781 | if (platform->driver->resume && platform->suspended) { | ||
782 | platform->driver->resume(cpu_dai); | ||
783 | platform->suspended = 0; | ||
784 | } | ||
785 | } | 775 | } |
786 | 776 | ||
787 | if (card->resume_post) | 777 | if (card->resume_post) |
@@ -792,8 +782,8 @@ static void soc_resume_deferred(struct work_struct *work) | |||
792 | /* userspace can access us now we are back as we were before */ | 782 | /* userspace can access us now we are back as we were before */ |
793 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); | 783 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); |
794 | 784 | ||
795 | /* Recheck all analogue paths too */ | 785 | /* Recheck all endpoints too, their state is affected by suspend */ |
796 | dapm_mark_io_dirty(&card->dapm); | 786 | dapm_mark_endpoints_dirty(card); |
797 | snd_soc_dapm_sync(&card->dapm); | 787 | snd_soc_dapm_sync(&card->dapm); |
798 | } | 788 | } |
799 | 789 | ||
@@ -1247,25 +1237,22 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num, | |||
1247 | return 0; | 1237 | return 0; |
1248 | } | 1238 | } |
1249 | 1239 | ||
1250 | static int soc_probe_codec_dai(struct snd_soc_card *card, | 1240 | static int soc_probe_dai(struct snd_soc_dai *dai, int order) |
1251 | struct snd_soc_dai *codec_dai, | ||
1252 | int order) | ||
1253 | { | 1241 | { |
1254 | int ret; | 1242 | int ret; |
1255 | 1243 | ||
1256 | if (!codec_dai->probed && codec_dai->driver->probe_order == order) { | 1244 | if (!dai->probed && dai->driver->probe_order == order) { |
1257 | if (codec_dai->driver->probe) { | 1245 | if (dai->driver->probe) { |
1258 | ret = codec_dai->driver->probe(codec_dai); | 1246 | ret = dai->driver->probe(dai); |
1259 | if (ret < 0) { | 1247 | if (ret < 0) { |
1260 | dev_err(codec_dai->dev, | 1248 | dev_err(dai->dev, |
1261 | "ASoC: failed to probe CODEC DAI %s: %d\n", | 1249 | "ASoC: failed to probe DAI %s: %d\n", |
1262 | codec_dai->name, ret); | 1250 | dai->name, ret); |
1263 | return ret; | 1251 | return ret; |
1264 | } | 1252 | } |
1265 | } | 1253 | } |
1266 | 1254 | ||
1267 | /* mark codec_dai as probed and add to card dai list */ | 1255 | dai->probed = 1; |
1268 | codec_dai->probed = 1; | ||
1269 | } | 1256 | } |
1270 | 1257 | ||
1271 | return 0; | 1258 | return 0; |
@@ -1315,40 +1302,22 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1315 | { | 1302 | { |
1316 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1303 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
1317 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1304 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1318 | struct snd_soc_platform *platform = rtd->platform; | ||
1319 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1305 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1320 | int i, ret; | 1306 | int i, ret; |
1321 | 1307 | ||
1322 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", | 1308 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", |
1323 | card->name, num, order); | 1309 | card->name, num, order); |
1324 | 1310 | ||
1325 | /* config components */ | ||
1326 | cpu_dai->platform = platform; | ||
1327 | cpu_dai->card = card; | ||
1328 | for (i = 0; i < rtd->num_codecs; i++) | ||
1329 | rtd->codec_dais[i]->card = card; | ||
1330 | |||
1331 | /* set default power off timeout */ | 1311 | /* set default power off timeout */ |
1332 | rtd->pmdown_time = pmdown_time; | 1312 | rtd->pmdown_time = pmdown_time; |
1333 | 1313 | ||
1334 | /* probe the cpu_dai */ | 1314 | ret = soc_probe_dai(cpu_dai, order); |
1335 | if (!cpu_dai->probed && | 1315 | if (ret) |
1336 | cpu_dai->driver->probe_order == order) { | 1316 | return ret; |
1337 | if (cpu_dai->driver->probe) { | ||
1338 | ret = cpu_dai->driver->probe(cpu_dai); | ||
1339 | if (ret < 0) { | ||
1340 | dev_err(cpu_dai->dev, | ||
1341 | "ASoC: failed to probe CPU DAI %s: %d\n", | ||
1342 | cpu_dai->name, ret); | ||
1343 | return ret; | ||
1344 | } | ||
1345 | } | ||
1346 | cpu_dai->probed = 1; | ||
1347 | } | ||
1348 | 1317 | ||
1349 | /* probe the CODEC DAI */ | 1318 | /* probe the CODEC DAI */ |
1350 | for (i = 0; i < rtd->num_codecs; i++) { | 1319 | for (i = 0; i < rtd->num_codecs; i++) { |
1351 | ret = soc_probe_codec_dai(card, rtd->codec_dais[i], order); | 1320 | ret = soc_probe_dai(rtd->codec_dais[i], order); |
1352 | if (ret) | 1321 | if (ret) |
1353 | return ret; | 1322 | return ret; |
1354 | } | 1323 | } |
@@ -2322,7 +2291,7 @@ EXPORT_SYMBOL_GPL(snd_soc_add_card_controls); | |||
2322 | int snd_soc_add_dai_controls(struct snd_soc_dai *dai, | 2291 | int snd_soc_add_dai_controls(struct snd_soc_dai *dai, |
2323 | const struct snd_kcontrol_new *controls, int num_controls) | 2292 | const struct snd_kcontrol_new *controls, int num_controls) |
2324 | { | 2293 | { |
2325 | struct snd_card *card = dai->card->snd_card; | 2294 | struct snd_card *card = dai->component->card->snd_card; |
2326 | 2295 | ||
2327 | return snd_soc_add_controls(card, dai->dev, controls, num_controls, | 2296 | return snd_soc_add_controls(card, dai->dev, controls, num_controls, |
2328 | NULL, dai); | 2297 | NULL, dai); |
@@ -2330,1020 +2299,6 @@ int snd_soc_add_dai_controls(struct snd_soc_dai *dai, | |||
2330 | EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); | 2299 | EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); |
2331 | 2300 | ||
2332 | /** | 2301 | /** |
2333 | * snd_soc_info_enum_double - enumerated double mixer info callback | ||
2334 | * @kcontrol: mixer control | ||
2335 | * @uinfo: control element information | ||
2336 | * | ||
2337 | * Callback to provide information about a double enumerated | ||
2338 | * mixer control. | ||
2339 | * | ||
2340 | * Returns 0 for success. | ||
2341 | */ | ||
2342 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | ||
2343 | struct snd_ctl_elem_info *uinfo) | ||
2344 | { | ||
2345 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
2346 | |||
2347 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2348 | uinfo->count = e->shift_l == e->shift_r ? 1 : 2; | ||
2349 | uinfo->value.enumerated.items = e->items; | ||
2350 | |||
2351 | if (uinfo->value.enumerated.item >= e->items) | ||
2352 | uinfo->value.enumerated.item = e->items - 1; | ||
2353 | strlcpy(uinfo->value.enumerated.name, | ||
2354 | e->texts[uinfo->value.enumerated.item], | ||
2355 | sizeof(uinfo->value.enumerated.name)); | ||
2356 | return 0; | ||
2357 | } | ||
2358 | EXPORT_SYMBOL_GPL(snd_soc_info_enum_double); | ||
2359 | |||
2360 | /** | ||
2361 | * snd_soc_get_enum_double - enumerated double mixer get callback | ||
2362 | * @kcontrol: mixer control | ||
2363 | * @ucontrol: control element information | ||
2364 | * | ||
2365 | * Callback to get the value of a double enumerated mixer. | ||
2366 | * | ||
2367 | * Returns 0 for success. | ||
2368 | */ | ||
2369 | int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, | ||
2370 | struct snd_ctl_elem_value *ucontrol) | ||
2371 | { | ||
2372 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2373 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
2374 | unsigned int val, item; | ||
2375 | unsigned int reg_val; | ||
2376 | int ret; | ||
2377 | |||
2378 | ret = snd_soc_component_read(component, e->reg, ®_val); | ||
2379 | if (ret) | ||
2380 | return ret; | ||
2381 | val = (reg_val >> e->shift_l) & e->mask; | ||
2382 | item = snd_soc_enum_val_to_item(e, val); | ||
2383 | ucontrol->value.enumerated.item[0] = item; | ||
2384 | if (e->shift_l != e->shift_r) { | ||
2385 | val = (reg_val >> e->shift_l) & e->mask; | ||
2386 | item = snd_soc_enum_val_to_item(e, val); | ||
2387 | ucontrol->value.enumerated.item[1] = item; | ||
2388 | } | ||
2389 | |||
2390 | return 0; | ||
2391 | } | ||
2392 | EXPORT_SYMBOL_GPL(snd_soc_get_enum_double); | ||
2393 | |||
2394 | /** | ||
2395 | * snd_soc_put_enum_double - enumerated double mixer put callback | ||
2396 | * @kcontrol: mixer control | ||
2397 | * @ucontrol: control element information | ||
2398 | * | ||
2399 | * Callback to set the value of a double enumerated mixer. | ||
2400 | * | ||
2401 | * Returns 0 for success. | ||
2402 | */ | ||
2403 | int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | ||
2404 | struct snd_ctl_elem_value *ucontrol) | ||
2405 | { | ||
2406 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2407 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
2408 | unsigned int *item = ucontrol->value.enumerated.item; | ||
2409 | unsigned int val; | ||
2410 | unsigned int mask; | ||
2411 | |||
2412 | if (item[0] >= e->items) | ||
2413 | return -EINVAL; | ||
2414 | val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; | ||
2415 | mask = e->mask << e->shift_l; | ||
2416 | if (e->shift_l != e->shift_r) { | ||
2417 | if (item[1] >= e->items) | ||
2418 | return -EINVAL; | ||
2419 | val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; | ||
2420 | mask |= e->mask << e->shift_r; | ||
2421 | } | ||
2422 | |||
2423 | return snd_soc_component_update_bits(component, e->reg, mask, val); | ||
2424 | } | ||
2425 | EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); | ||
2426 | |||
2427 | /** | ||
2428 | * snd_soc_read_signed - Read a codec register and interprete as signed value | ||
2429 | * @component: component | ||
2430 | * @reg: Register to read | ||
2431 | * @mask: Mask to use after shifting the register value | ||
2432 | * @shift: Right shift of register value | ||
2433 | * @sign_bit: Bit that describes if a number is negative or not. | ||
2434 | * @signed_val: Pointer to where the read value should be stored | ||
2435 | * | ||
2436 | * This functions reads a codec register. The register value is shifted right | ||
2437 | * by 'shift' bits and masked with the given 'mask'. Afterwards it translates | ||
2438 | * the given registervalue into a signed integer if sign_bit is non-zero. | ||
2439 | * | ||
2440 | * Returns 0 on sucess, otherwise an error value | ||
2441 | */ | ||
2442 | static int snd_soc_read_signed(struct snd_soc_component *component, | ||
2443 | unsigned int reg, unsigned int mask, unsigned int shift, | ||
2444 | unsigned int sign_bit, int *signed_val) | ||
2445 | { | ||
2446 | int ret; | ||
2447 | unsigned int val; | ||
2448 | |||
2449 | ret = snd_soc_component_read(component, reg, &val); | ||
2450 | if (ret < 0) | ||
2451 | return ret; | ||
2452 | |||
2453 | val = (val >> shift) & mask; | ||
2454 | |||
2455 | if (!sign_bit) { | ||
2456 | *signed_val = val; | ||
2457 | return 0; | ||
2458 | } | ||
2459 | |||
2460 | /* non-negative number */ | ||
2461 | if (!(val & BIT(sign_bit))) { | ||
2462 | *signed_val = val; | ||
2463 | return 0; | ||
2464 | } | ||
2465 | |||
2466 | ret = val; | ||
2467 | |||
2468 | /* | ||
2469 | * The register most probably does not contain a full-sized int. | ||
2470 | * Instead we have an arbitrary number of bits in a signed | ||
2471 | * representation which has to be translated into a full-sized int. | ||
2472 | * This is done by filling up all bits above the sign-bit. | ||
2473 | */ | ||
2474 | ret |= ~((int)(BIT(sign_bit) - 1)); | ||
2475 | |||
2476 | *signed_val = ret; | ||
2477 | |||
2478 | return 0; | ||
2479 | } | ||
2480 | |||
2481 | /** | ||
2482 | * snd_soc_info_volsw - single mixer info callback | ||
2483 | * @kcontrol: mixer control | ||
2484 | * @uinfo: control element information | ||
2485 | * | ||
2486 | * Callback to provide information about a single mixer control, or a double | ||
2487 | * mixer control that spans 2 registers. | ||
2488 | * | ||
2489 | * Returns 0 for success. | ||
2490 | */ | ||
2491 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | ||
2492 | struct snd_ctl_elem_info *uinfo) | ||
2493 | { | ||
2494 | struct soc_mixer_control *mc = | ||
2495 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2496 | int platform_max; | ||
2497 | |||
2498 | if (!mc->platform_max) | ||
2499 | mc->platform_max = mc->max; | ||
2500 | platform_max = mc->platform_max; | ||
2501 | |||
2502 | if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume")) | ||
2503 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2504 | else | ||
2505 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2506 | |||
2507 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | ||
2508 | uinfo->value.integer.min = 0; | ||
2509 | uinfo->value.integer.max = platform_max - mc->min; | ||
2510 | return 0; | ||
2511 | } | ||
2512 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | ||
2513 | |||
2514 | /** | ||
2515 | * snd_soc_get_volsw - single mixer get callback | ||
2516 | * @kcontrol: mixer control | ||
2517 | * @ucontrol: control element information | ||
2518 | * | ||
2519 | * Callback to get the value of a single mixer control, or a double mixer | ||
2520 | * control that spans 2 registers. | ||
2521 | * | ||
2522 | * Returns 0 for success. | ||
2523 | */ | ||
2524 | int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | ||
2525 | struct snd_ctl_elem_value *ucontrol) | ||
2526 | { | ||
2527 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2528 | struct soc_mixer_control *mc = | ||
2529 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2530 | unsigned int reg = mc->reg; | ||
2531 | unsigned int reg2 = mc->rreg; | ||
2532 | unsigned int shift = mc->shift; | ||
2533 | unsigned int rshift = mc->rshift; | ||
2534 | int max = mc->max; | ||
2535 | int min = mc->min; | ||
2536 | int sign_bit = mc->sign_bit; | ||
2537 | unsigned int mask = (1 << fls(max)) - 1; | ||
2538 | unsigned int invert = mc->invert; | ||
2539 | int val; | ||
2540 | int ret; | ||
2541 | |||
2542 | if (sign_bit) | ||
2543 | mask = BIT(sign_bit + 1) - 1; | ||
2544 | |||
2545 | ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); | ||
2546 | if (ret) | ||
2547 | return ret; | ||
2548 | |||
2549 | ucontrol->value.integer.value[0] = val - min; | ||
2550 | if (invert) | ||
2551 | ucontrol->value.integer.value[0] = | ||
2552 | max - ucontrol->value.integer.value[0]; | ||
2553 | |||
2554 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2555 | if (reg == reg2) | ||
2556 | ret = snd_soc_read_signed(component, reg, mask, rshift, | ||
2557 | sign_bit, &val); | ||
2558 | else | ||
2559 | ret = snd_soc_read_signed(component, reg2, mask, shift, | ||
2560 | sign_bit, &val); | ||
2561 | if (ret) | ||
2562 | return ret; | ||
2563 | |||
2564 | ucontrol->value.integer.value[1] = val - min; | ||
2565 | if (invert) | ||
2566 | ucontrol->value.integer.value[1] = | ||
2567 | max - ucontrol->value.integer.value[1]; | ||
2568 | } | ||
2569 | |||
2570 | return 0; | ||
2571 | } | ||
2572 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw); | ||
2573 | |||
2574 | /** | ||
2575 | * snd_soc_put_volsw - single mixer put callback | ||
2576 | * @kcontrol: mixer control | ||
2577 | * @ucontrol: control element information | ||
2578 | * | ||
2579 | * Callback to set the value of a single mixer control, or a double mixer | ||
2580 | * control that spans 2 registers. | ||
2581 | * | ||
2582 | * Returns 0 for success. | ||
2583 | */ | ||
2584 | int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | ||
2585 | struct snd_ctl_elem_value *ucontrol) | ||
2586 | { | ||
2587 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2588 | struct soc_mixer_control *mc = | ||
2589 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2590 | unsigned int reg = mc->reg; | ||
2591 | unsigned int reg2 = mc->rreg; | ||
2592 | unsigned int shift = mc->shift; | ||
2593 | unsigned int rshift = mc->rshift; | ||
2594 | int max = mc->max; | ||
2595 | int min = mc->min; | ||
2596 | unsigned int sign_bit = mc->sign_bit; | ||
2597 | unsigned int mask = (1 << fls(max)) - 1; | ||
2598 | unsigned int invert = mc->invert; | ||
2599 | int err; | ||
2600 | bool type_2r = false; | ||
2601 | unsigned int val2 = 0; | ||
2602 | unsigned int val, val_mask; | ||
2603 | |||
2604 | if (sign_bit) | ||
2605 | mask = BIT(sign_bit + 1) - 1; | ||
2606 | |||
2607 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
2608 | if (invert) | ||
2609 | val = max - val; | ||
2610 | val_mask = mask << shift; | ||
2611 | val = val << shift; | ||
2612 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2613 | val2 = ((ucontrol->value.integer.value[1] + min) & mask); | ||
2614 | if (invert) | ||
2615 | val2 = max - val2; | ||
2616 | if (reg == reg2) { | ||
2617 | val_mask |= mask << rshift; | ||
2618 | val |= val2 << rshift; | ||
2619 | } else { | ||
2620 | val2 = val2 << shift; | ||
2621 | type_2r = true; | ||
2622 | } | ||
2623 | } | ||
2624 | err = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
2625 | if (err < 0) | ||
2626 | return err; | ||
2627 | |||
2628 | if (type_2r) | ||
2629 | err = snd_soc_component_update_bits(component, reg2, val_mask, | ||
2630 | val2); | ||
2631 | |||
2632 | return err; | ||
2633 | } | ||
2634 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw); | ||
2635 | |||
2636 | /** | ||
2637 | * snd_soc_get_volsw_sx - single mixer get callback | ||
2638 | * @kcontrol: mixer control | ||
2639 | * @ucontrol: control element information | ||
2640 | * | ||
2641 | * Callback to get the value of a single mixer control, or a double mixer | ||
2642 | * control that spans 2 registers. | ||
2643 | * | ||
2644 | * Returns 0 for success. | ||
2645 | */ | ||
2646 | int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, | ||
2647 | struct snd_ctl_elem_value *ucontrol) | ||
2648 | { | ||
2649 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2650 | struct soc_mixer_control *mc = | ||
2651 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2652 | unsigned int reg = mc->reg; | ||
2653 | unsigned int reg2 = mc->rreg; | ||
2654 | unsigned int shift = mc->shift; | ||
2655 | unsigned int rshift = mc->rshift; | ||
2656 | int max = mc->max; | ||
2657 | int min = mc->min; | ||
2658 | int mask = (1 << (fls(min + max) - 1)) - 1; | ||
2659 | unsigned int val; | ||
2660 | int ret; | ||
2661 | |||
2662 | ret = snd_soc_component_read(component, reg, &val); | ||
2663 | if (ret < 0) | ||
2664 | return ret; | ||
2665 | |||
2666 | ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; | ||
2667 | |||
2668 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2669 | ret = snd_soc_component_read(component, reg2, &val); | ||
2670 | if (ret < 0) | ||
2671 | return ret; | ||
2672 | |||
2673 | val = ((val >> rshift) - min) & mask; | ||
2674 | ucontrol->value.integer.value[1] = val; | ||
2675 | } | ||
2676 | |||
2677 | return 0; | ||
2678 | } | ||
2679 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx); | ||
2680 | |||
2681 | /** | ||
2682 | * snd_soc_put_volsw_sx - double mixer set callback | ||
2683 | * @kcontrol: mixer control | ||
2684 | * @uinfo: control element information | ||
2685 | * | ||
2686 | * Callback to set the value of a double mixer control that spans 2 registers. | ||
2687 | * | ||
2688 | * Returns 0 for success. | ||
2689 | */ | ||
2690 | int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, | ||
2691 | struct snd_ctl_elem_value *ucontrol) | ||
2692 | { | ||
2693 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2694 | struct soc_mixer_control *mc = | ||
2695 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2696 | |||
2697 | unsigned int reg = mc->reg; | ||
2698 | unsigned int reg2 = mc->rreg; | ||
2699 | unsigned int shift = mc->shift; | ||
2700 | unsigned int rshift = mc->rshift; | ||
2701 | int max = mc->max; | ||
2702 | int min = mc->min; | ||
2703 | int mask = (1 << (fls(min + max) - 1)) - 1; | ||
2704 | int err = 0; | ||
2705 | unsigned int val, val_mask, val2 = 0; | ||
2706 | |||
2707 | val_mask = mask << shift; | ||
2708 | val = (ucontrol->value.integer.value[0] + min) & mask; | ||
2709 | val = val << shift; | ||
2710 | |||
2711 | err = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
2712 | if (err < 0) | ||
2713 | return err; | ||
2714 | |||
2715 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2716 | val_mask = mask << rshift; | ||
2717 | val2 = (ucontrol->value.integer.value[1] + min) & mask; | ||
2718 | val2 = val2 << rshift; | ||
2719 | |||
2720 | err = snd_soc_component_update_bits(component, reg2, val_mask, | ||
2721 | val2); | ||
2722 | } | ||
2723 | return err; | ||
2724 | } | ||
2725 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); | ||
2726 | |||
2727 | /** | ||
2728 | * snd_soc_info_volsw_s8 - signed mixer info callback | ||
2729 | * @kcontrol: mixer control | ||
2730 | * @uinfo: control element information | ||
2731 | * | ||
2732 | * Callback to provide information about a signed mixer control. | ||
2733 | * | ||
2734 | * Returns 0 for success. | ||
2735 | */ | ||
2736 | int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, | ||
2737 | struct snd_ctl_elem_info *uinfo) | ||
2738 | { | ||
2739 | struct soc_mixer_control *mc = | ||
2740 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2741 | int platform_max; | ||
2742 | int min = mc->min; | ||
2743 | |||
2744 | if (!mc->platform_max) | ||
2745 | mc->platform_max = mc->max; | ||
2746 | platform_max = mc->platform_max; | ||
2747 | |||
2748 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2749 | uinfo->count = 2; | ||
2750 | uinfo->value.integer.min = 0; | ||
2751 | uinfo->value.integer.max = platform_max - min; | ||
2752 | return 0; | ||
2753 | } | ||
2754 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8); | ||
2755 | |||
2756 | /** | ||
2757 | * snd_soc_get_volsw_s8 - signed mixer get callback | ||
2758 | * @kcontrol: mixer control | ||
2759 | * @ucontrol: control element information | ||
2760 | * | ||
2761 | * Callback to get the value of a signed mixer control. | ||
2762 | * | ||
2763 | * Returns 0 for success. | ||
2764 | */ | ||
2765 | int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, | ||
2766 | struct snd_ctl_elem_value *ucontrol) | ||
2767 | { | ||
2768 | struct soc_mixer_control *mc = | ||
2769 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2770 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2771 | unsigned int reg = mc->reg; | ||
2772 | unsigned int val; | ||
2773 | int min = mc->min; | ||
2774 | int ret; | ||
2775 | |||
2776 | ret = snd_soc_component_read(component, reg, &val); | ||
2777 | if (ret) | ||
2778 | return ret; | ||
2779 | |||
2780 | ucontrol->value.integer.value[0] = | ||
2781 | ((signed char)(val & 0xff))-min; | ||
2782 | ucontrol->value.integer.value[1] = | ||
2783 | ((signed char)((val >> 8) & 0xff))-min; | ||
2784 | return 0; | ||
2785 | } | ||
2786 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_s8); | ||
2787 | |||
2788 | /** | ||
2789 | * snd_soc_put_volsw_sgn - signed mixer put callback | ||
2790 | * @kcontrol: mixer control | ||
2791 | * @ucontrol: control element information | ||
2792 | * | ||
2793 | * Callback to set the value of a signed mixer control. | ||
2794 | * | ||
2795 | * Returns 0 for success. | ||
2796 | */ | ||
2797 | int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, | ||
2798 | struct snd_ctl_elem_value *ucontrol) | ||
2799 | { | ||
2800 | struct soc_mixer_control *mc = | ||
2801 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2802 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2803 | unsigned int reg = mc->reg; | ||
2804 | int min = mc->min; | ||
2805 | unsigned int val; | ||
2806 | |||
2807 | val = (ucontrol->value.integer.value[0]+min) & 0xff; | ||
2808 | val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8; | ||
2809 | |||
2810 | return snd_soc_component_update_bits(component, reg, 0xffff, val); | ||
2811 | } | ||
2812 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); | ||
2813 | |||
2814 | /** | ||
2815 | * snd_soc_info_volsw_range - single mixer info callback with range. | ||
2816 | * @kcontrol: mixer control | ||
2817 | * @uinfo: control element information | ||
2818 | * | ||
2819 | * Callback to provide information, within a range, about a single | ||
2820 | * mixer control. | ||
2821 | * | ||
2822 | * returns 0 for success. | ||
2823 | */ | ||
2824 | int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, | ||
2825 | struct snd_ctl_elem_info *uinfo) | ||
2826 | { | ||
2827 | struct soc_mixer_control *mc = | ||
2828 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2829 | int platform_max; | ||
2830 | int min = mc->min; | ||
2831 | |||
2832 | if (!mc->platform_max) | ||
2833 | mc->platform_max = mc->max; | ||
2834 | platform_max = mc->platform_max; | ||
2835 | |||
2836 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2837 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | ||
2838 | uinfo->value.integer.min = 0; | ||
2839 | uinfo->value.integer.max = platform_max - min; | ||
2840 | |||
2841 | return 0; | ||
2842 | } | ||
2843 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); | ||
2844 | |||
2845 | /** | ||
2846 | * snd_soc_put_volsw_range - single mixer put value callback with range. | ||
2847 | * @kcontrol: mixer control | ||
2848 | * @ucontrol: control element information | ||
2849 | * | ||
2850 | * Callback to set the value, within a range, for a single mixer control. | ||
2851 | * | ||
2852 | * Returns 0 for success. | ||
2853 | */ | ||
2854 | int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | ||
2855 | struct snd_ctl_elem_value *ucontrol) | ||
2856 | { | ||
2857 | struct soc_mixer_control *mc = | ||
2858 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2859 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2860 | unsigned int reg = mc->reg; | ||
2861 | unsigned int rreg = mc->rreg; | ||
2862 | unsigned int shift = mc->shift; | ||
2863 | int min = mc->min; | ||
2864 | int max = mc->max; | ||
2865 | unsigned int mask = (1 << fls(max)) - 1; | ||
2866 | unsigned int invert = mc->invert; | ||
2867 | unsigned int val, val_mask; | ||
2868 | int ret; | ||
2869 | |||
2870 | if (invert) | ||
2871 | val = (max - ucontrol->value.integer.value[0]) & mask; | ||
2872 | else | ||
2873 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
2874 | val_mask = mask << shift; | ||
2875 | val = val << shift; | ||
2876 | |||
2877 | ret = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
2878 | if (ret < 0) | ||
2879 | return ret; | ||
2880 | |||
2881 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2882 | if (invert) | ||
2883 | val = (max - ucontrol->value.integer.value[1]) & mask; | ||
2884 | else | ||
2885 | val = ((ucontrol->value.integer.value[1] + min) & mask); | ||
2886 | val_mask = mask << shift; | ||
2887 | val = val << shift; | ||
2888 | |||
2889 | ret = snd_soc_component_update_bits(component, rreg, val_mask, | ||
2890 | val); | ||
2891 | } | ||
2892 | |||
2893 | return ret; | ||
2894 | } | ||
2895 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); | ||
2896 | |||
2897 | /** | ||
2898 | * snd_soc_get_volsw_range - single mixer get callback with range | ||
2899 | * @kcontrol: mixer control | ||
2900 | * @ucontrol: control element information | ||
2901 | * | ||
2902 | * Callback to get the value, within a range, of a single mixer control. | ||
2903 | * | ||
2904 | * Returns 0 for success. | ||
2905 | */ | ||
2906 | int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | ||
2907 | struct snd_ctl_elem_value *ucontrol) | ||
2908 | { | ||
2909 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2910 | struct soc_mixer_control *mc = | ||
2911 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2912 | unsigned int reg = mc->reg; | ||
2913 | unsigned int rreg = mc->rreg; | ||
2914 | unsigned int shift = mc->shift; | ||
2915 | int min = mc->min; | ||
2916 | int max = mc->max; | ||
2917 | unsigned int mask = (1 << fls(max)) - 1; | ||
2918 | unsigned int invert = mc->invert; | ||
2919 | unsigned int val; | ||
2920 | int ret; | ||
2921 | |||
2922 | ret = snd_soc_component_read(component, reg, &val); | ||
2923 | if (ret) | ||
2924 | return ret; | ||
2925 | |||
2926 | ucontrol->value.integer.value[0] = (val >> shift) & mask; | ||
2927 | if (invert) | ||
2928 | ucontrol->value.integer.value[0] = | ||
2929 | max - ucontrol->value.integer.value[0]; | ||
2930 | else | ||
2931 | ucontrol->value.integer.value[0] = | ||
2932 | ucontrol->value.integer.value[0] - min; | ||
2933 | |||
2934 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2935 | ret = snd_soc_component_read(component, rreg, &val); | ||
2936 | if (ret) | ||
2937 | return ret; | ||
2938 | |||
2939 | ucontrol->value.integer.value[1] = (val >> shift) & mask; | ||
2940 | if (invert) | ||
2941 | ucontrol->value.integer.value[1] = | ||
2942 | max - ucontrol->value.integer.value[1]; | ||
2943 | else | ||
2944 | ucontrol->value.integer.value[1] = | ||
2945 | ucontrol->value.integer.value[1] - min; | ||
2946 | } | ||
2947 | |||
2948 | return 0; | ||
2949 | } | ||
2950 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); | ||
2951 | |||
2952 | /** | ||
2953 | * snd_soc_limit_volume - Set new limit to an existing volume control. | ||
2954 | * | ||
2955 | * @codec: where to look for the control | ||
2956 | * @name: Name of the control | ||
2957 | * @max: new maximum limit | ||
2958 | * | ||
2959 | * Return 0 for success, else error. | ||
2960 | */ | ||
2961 | int snd_soc_limit_volume(struct snd_soc_codec *codec, | ||
2962 | const char *name, int max) | ||
2963 | { | ||
2964 | struct snd_card *card = codec->component.card->snd_card; | ||
2965 | struct snd_kcontrol *kctl; | ||
2966 | struct soc_mixer_control *mc; | ||
2967 | int found = 0; | ||
2968 | int ret = -EINVAL; | ||
2969 | |||
2970 | /* Sanity check for name and max */ | ||
2971 | if (unlikely(!name || max <= 0)) | ||
2972 | return -EINVAL; | ||
2973 | |||
2974 | list_for_each_entry(kctl, &card->controls, list) { | ||
2975 | if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) { | ||
2976 | found = 1; | ||
2977 | break; | ||
2978 | } | ||
2979 | } | ||
2980 | if (found) { | ||
2981 | mc = (struct soc_mixer_control *)kctl->private_value; | ||
2982 | if (max <= mc->max) { | ||
2983 | mc->platform_max = max; | ||
2984 | ret = 0; | ||
2985 | } | ||
2986 | } | ||
2987 | return ret; | ||
2988 | } | ||
2989 | EXPORT_SYMBOL_GPL(snd_soc_limit_volume); | ||
2990 | |||
2991 | int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, | ||
2992 | struct snd_ctl_elem_info *uinfo) | ||
2993 | { | ||
2994 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2995 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
2996 | |||
2997 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
2998 | uinfo->count = params->num_regs * component->val_bytes; | ||
2999 | |||
3000 | return 0; | ||
3001 | } | ||
3002 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info); | ||
3003 | |||
3004 | int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, | ||
3005 | struct snd_ctl_elem_value *ucontrol) | ||
3006 | { | ||
3007 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3008 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
3009 | int ret; | ||
3010 | |||
3011 | if (component->regmap) | ||
3012 | ret = regmap_raw_read(component->regmap, params->base, | ||
3013 | ucontrol->value.bytes.data, | ||
3014 | params->num_regs * component->val_bytes); | ||
3015 | else | ||
3016 | ret = -EINVAL; | ||
3017 | |||
3018 | /* Hide any masked bytes to ensure consistent data reporting */ | ||
3019 | if (ret == 0 && params->mask) { | ||
3020 | switch (component->val_bytes) { | ||
3021 | case 1: | ||
3022 | ucontrol->value.bytes.data[0] &= ~params->mask; | ||
3023 | break; | ||
3024 | case 2: | ||
3025 | ((u16 *)(&ucontrol->value.bytes.data))[0] | ||
3026 | &= cpu_to_be16(~params->mask); | ||
3027 | break; | ||
3028 | case 4: | ||
3029 | ((u32 *)(&ucontrol->value.bytes.data))[0] | ||
3030 | &= cpu_to_be32(~params->mask); | ||
3031 | break; | ||
3032 | default: | ||
3033 | return -EINVAL; | ||
3034 | } | ||
3035 | } | ||
3036 | |||
3037 | return ret; | ||
3038 | } | ||
3039 | EXPORT_SYMBOL_GPL(snd_soc_bytes_get); | ||
3040 | |||
3041 | int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, | ||
3042 | struct snd_ctl_elem_value *ucontrol) | ||
3043 | { | ||
3044 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3045 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
3046 | int ret, len; | ||
3047 | unsigned int val, mask; | ||
3048 | void *data; | ||
3049 | |||
3050 | if (!component->regmap || !params->num_regs) | ||
3051 | return -EINVAL; | ||
3052 | |||
3053 | len = params->num_regs * component->val_bytes; | ||
3054 | |||
3055 | data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); | ||
3056 | if (!data) | ||
3057 | return -ENOMEM; | ||
3058 | |||
3059 | /* | ||
3060 | * If we've got a mask then we need to preserve the register | ||
3061 | * bits. We shouldn't modify the incoming data so take a | ||
3062 | * copy. | ||
3063 | */ | ||
3064 | if (params->mask) { | ||
3065 | ret = regmap_read(component->regmap, params->base, &val); | ||
3066 | if (ret != 0) | ||
3067 | goto out; | ||
3068 | |||
3069 | val &= params->mask; | ||
3070 | |||
3071 | switch (component->val_bytes) { | ||
3072 | case 1: | ||
3073 | ((u8 *)data)[0] &= ~params->mask; | ||
3074 | ((u8 *)data)[0] |= val; | ||
3075 | break; | ||
3076 | case 2: | ||
3077 | mask = ~params->mask; | ||
3078 | ret = regmap_parse_val(component->regmap, | ||
3079 | &mask, &mask); | ||
3080 | if (ret != 0) | ||
3081 | goto out; | ||
3082 | |||
3083 | ((u16 *)data)[0] &= mask; | ||
3084 | |||
3085 | ret = regmap_parse_val(component->regmap, | ||
3086 | &val, &val); | ||
3087 | if (ret != 0) | ||
3088 | goto out; | ||
3089 | |||
3090 | ((u16 *)data)[0] |= val; | ||
3091 | break; | ||
3092 | case 4: | ||
3093 | mask = ~params->mask; | ||
3094 | ret = regmap_parse_val(component->regmap, | ||
3095 | &mask, &mask); | ||
3096 | if (ret != 0) | ||
3097 | goto out; | ||
3098 | |||
3099 | ((u32 *)data)[0] &= mask; | ||
3100 | |||
3101 | ret = regmap_parse_val(component->regmap, | ||
3102 | &val, &val); | ||
3103 | if (ret != 0) | ||
3104 | goto out; | ||
3105 | |||
3106 | ((u32 *)data)[0] |= val; | ||
3107 | break; | ||
3108 | default: | ||
3109 | ret = -EINVAL; | ||
3110 | goto out; | ||
3111 | } | ||
3112 | } | ||
3113 | |||
3114 | ret = regmap_raw_write(component->regmap, params->base, | ||
3115 | data, len); | ||
3116 | |||
3117 | out: | ||
3118 | kfree(data); | ||
3119 | |||
3120 | return ret; | ||
3121 | } | ||
3122 | EXPORT_SYMBOL_GPL(snd_soc_bytes_put); | ||
3123 | |||
3124 | int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, | ||
3125 | struct snd_ctl_elem_info *ucontrol) | ||
3126 | { | ||
3127 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
3128 | |||
3129 | ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
3130 | ucontrol->count = params->max; | ||
3131 | |||
3132 | return 0; | ||
3133 | } | ||
3134 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); | ||
3135 | |||
3136 | int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, | ||
3137 | unsigned int size, unsigned int __user *tlv) | ||
3138 | { | ||
3139 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
3140 | unsigned int count = size < params->max ? size : params->max; | ||
3141 | int ret = -ENXIO; | ||
3142 | |||
3143 | switch (op_flag) { | ||
3144 | case SNDRV_CTL_TLV_OP_READ: | ||
3145 | if (params->get) | ||
3146 | ret = params->get(tlv, count); | ||
3147 | break; | ||
3148 | case SNDRV_CTL_TLV_OP_WRITE: | ||
3149 | if (params->put) | ||
3150 | ret = params->put(tlv, count); | ||
3151 | break; | ||
3152 | } | ||
3153 | return ret; | ||
3154 | } | ||
3155 | EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); | ||
3156 | |||
3157 | /** | ||
3158 | * snd_soc_info_xr_sx - signed multi register info callback | ||
3159 | * @kcontrol: mreg control | ||
3160 | * @uinfo: control element information | ||
3161 | * | ||
3162 | * Callback to provide information of a control that can | ||
3163 | * span multiple codec registers which together | ||
3164 | * forms a single signed value in a MSB/LSB manner. | ||
3165 | * | ||
3166 | * Returns 0 for success. | ||
3167 | */ | ||
3168 | int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, | ||
3169 | struct snd_ctl_elem_info *uinfo) | ||
3170 | { | ||
3171 | struct soc_mreg_control *mc = | ||
3172 | (struct soc_mreg_control *)kcontrol->private_value; | ||
3173 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
3174 | uinfo->count = 1; | ||
3175 | uinfo->value.integer.min = mc->min; | ||
3176 | uinfo->value.integer.max = mc->max; | ||
3177 | |||
3178 | return 0; | ||
3179 | } | ||
3180 | EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx); | ||
3181 | |||
3182 | /** | ||
3183 | * snd_soc_get_xr_sx - signed multi register get callback | ||
3184 | * @kcontrol: mreg control | ||
3185 | * @ucontrol: control element information | ||
3186 | * | ||
3187 | * Callback to get the value of a control that can span | ||
3188 | * multiple codec registers which together forms a single | ||
3189 | * signed value in a MSB/LSB manner. The control supports | ||
3190 | * specifying total no of bits used to allow for bitfields | ||
3191 | * across the multiple codec registers. | ||
3192 | * | ||
3193 | * Returns 0 for success. | ||
3194 | */ | ||
3195 | int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, | ||
3196 | struct snd_ctl_elem_value *ucontrol) | ||
3197 | { | ||
3198 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3199 | struct soc_mreg_control *mc = | ||
3200 | (struct soc_mreg_control *)kcontrol->private_value; | ||
3201 | unsigned int regbase = mc->regbase; | ||
3202 | unsigned int regcount = mc->regcount; | ||
3203 | unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; | ||
3204 | unsigned int regwmask = (1<<regwshift)-1; | ||
3205 | unsigned int invert = mc->invert; | ||
3206 | unsigned long mask = (1UL<<mc->nbits)-1; | ||
3207 | long min = mc->min; | ||
3208 | long max = mc->max; | ||
3209 | long val = 0; | ||
3210 | unsigned int regval; | ||
3211 | unsigned int i; | ||
3212 | int ret; | ||
3213 | |||
3214 | for (i = 0; i < regcount; i++) { | ||
3215 | ret = snd_soc_component_read(component, regbase+i, ®val); | ||
3216 | if (ret) | ||
3217 | return ret; | ||
3218 | val |= (regval & regwmask) << (regwshift*(regcount-i-1)); | ||
3219 | } | ||
3220 | val &= mask; | ||
3221 | if (min < 0 && val > max) | ||
3222 | val |= ~mask; | ||
3223 | if (invert) | ||
3224 | val = max - val; | ||
3225 | ucontrol->value.integer.value[0] = val; | ||
3226 | |||
3227 | return 0; | ||
3228 | } | ||
3229 | EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx); | ||
3230 | |||
3231 | /** | ||
3232 | * snd_soc_put_xr_sx - signed multi register get callback | ||
3233 | * @kcontrol: mreg control | ||
3234 | * @ucontrol: control element information | ||
3235 | * | ||
3236 | * Callback to set the value of a control that can span | ||
3237 | * multiple codec registers which together forms a single | ||
3238 | * signed value in a MSB/LSB manner. The control supports | ||
3239 | * specifying total no of bits used to allow for bitfields | ||
3240 | * across the multiple codec registers. | ||
3241 | * | ||
3242 | * Returns 0 for success. | ||
3243 | */ | ||
3244 | int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, | ||
3245 | struct snd_ctl_elem_value *ucontrol) | ||
3246 | { | ||
3247 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3248 | struct soc_mreg_control *mc = | ||
3249 | (struct soc_mreg_control *)kcontrol->private_value; | ||
3250 | unsigned int regbase = mc->regbase; | ||
3251 | unsigned int regcount = mc->regcount; | ||
3252 | unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; | ||
3253 | unsigned int regwmask = (1<<regwshift)-1; | ||
3254 | unsigned int invert = mc->invert; | ||
3255 | unsigned long mask = (1UL<<mc->nbits)-1; | ||
3256 | long max = mc->max; | ||
3257 | long val = ucontrol->value.integer.value[0]; | ||
3258 | unsigned int i, regval, regmask; | ||
3259 | int err; | ||
3260 | |||
3261 | if (invert) | ||
3262 | val = max - val; | ||
3263 | val &= mask; | ||
3264 | for (i = 0; i < regcount; i++) { | ||
3265 | regval = (val >> (regwshift*(regcount-i-1))) & regwmask; | ||
3266 | regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; | ||
3267 | err = snd_soc_component_update_bits(component, regbase+i, | ||
3268 | regmask, regval); | ||
3269 | if (err < 0) | ||
3270 | return err; | ||
3271 | } | ||
3272 | |||
3273 | return 0; | ||
3274 | } | ||
3275 | EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx); | ||
3276 | |||
3277 | /** | ||
3278 | * snd_soc_get_strobe - strobe get callback | ||
3279 | * @kcontrol: mixer control | ||
3280 | * @ucontrol: control element information | ||
3281 | * | ||
3282 | * Callback get the value of a strobe mixer control. | ||
3283 | * | ||
3284 | * Returns 0 for success. | ||
3285 | */ | ||
3286 | int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, | ||
3287 | struct snd_ctl_elem_value *ucontrol) | ||
3288 | { | ||
3289 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3290 | struct soc_mixer_control *mc = | ||
3291 | (struct soc_mixer_control *)kcontrol->private_value; | ||
3292 | unsigned int reg = mc->reg; | ||
3293 | unsigned int shift = mc->shift; | ||
3294 | unsigned int mask = 1 << shift; | ||
3295 | unsigned int invert = mc->invert != 0; | ||
3296 | unsigned int val; | ||
3297 | int ret; | ||
3298 | |||
3299 | ret = snd_soc_component_read(component, reg, &val); | ||
3300 | if (ret) | ||
3301 | return ret; | ||
3302 | |||
3303 | val &= mask; | ||
3304 | |||
3305 | if (shift != 0 && val != 0) | ||
3306 | val = val >> shift; | ||
3307 | ucontrol->value.enumerated.item[0] = val ^ invert; | ||
3308 | |||
3309 | return 0; | ||
3310 | } | ||
3311 | EXPORT_SYMBOL_GPL(snd_soc_get_strobe); | ||
3312 | |||
3313 | /** | ||
3314 | * snd_soc_put_strobe - strobe put callback | ||
3315 | * @kcontrol: mixer control | ||
3316 | * @ucontrol: control element information | ||
3317 | * | ||
3318 | * Callback strobe a register bit to high then low (or the inverse) | ||
3319 | * in one pass of a single mixer enum control. | ||
3320 | * | ||
3321 | * Returns 1 for success. | ||
3322 | */ | ||
3323 | int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, | ||
3324 | struct snd_ctl_elem_value *ucontrol) | ||
3325 | { | ||
3326 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3327 | struct soc_mixer_control *mc = | ||
3328 | (struct soc_mixer_control *)kcontrol->private_value; | ||
3329 | unsigned int reg = mc->reg; | ||
3330 | unsigned int shift = mc->shift; | ||
3331 | unsigned int mask = 1 << shift; | ||
3332 | unsigned int invert = mc->invert != 0; | ||
3333 | unsigned int strobe = ucontrol->value.enumerated.item[0] != 0; | ||
3334 | unsigned int val1 = (strobe ^ invert) ? mask : 0; | ||
3335 | unsigned int val2 = (strobe ^ invert) ? 0 : mask; | ||
3336 | int err; | ||
3337 | |||
3338 | err = snd_soc_component_update_bits(component, reg, mask, val1); | ||
3339 | if (err < 0) | ||
3340 | return err; | ||
3341 | |||
3342 | return snd_soc_component_update_bits(component, reg, mask, val2); | ||
3343 | } | ||
3344 | EXPORT_SYMBOL_GPL(snd_soc_put_strobe); | ||
3345 | |||
3346 | /** | ||
3347 | * snd_soc_dai_set_sysclk - configure DAI system or master clock. | 2302 | * snd_soc_dai_set_sysclk - configure DAI system or master clock. |
3348 | * @dai: DAI | 2303 | * @dai: DAI |
3349 | * @clk_id: DAI specific clock ID | 2304 | * @clk_id: DAI specific clock ID |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c61cb9cedbcd..c5136bb1f982 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -159,27 +159,135 @@ static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) | |||
159 | } | 159 | } |
160 | } | 160 | } |
161 | 161 | ||
162 | void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) | 162 | /* |
163 | * dapm_widget_invalidate_input_paths() - Invalidate the cached number of input | ||
164 | * paths | ||
165 | * @w: The widget for which to invalidate the cached number of input paths | ||
166 | * | ||
167 | * The function resets the cached number of inputs for the specified widget and | ||
168 | * all widgets that can be reached via outgoing paths from the widget. | ||
169 | * | ||
170 | * This function must be called if the number of input paths for a widget might | ||
171 | * have changed. E.g. if the source state of a widget changes or a path is added | ||
172 | * or activated with the widget as the sink. | ||
173 | */ | ||
174 | static void dapm_widget_invalidate_input_paths(struct snd_soc_dapm_widget *w) | ||
175 | { | ||
176 | struct snd_soc_dapm_widget *sink; | ||
177 | struct snd_soc_dapm_path *p; | ||
178 | LIST_HEAD(list); | ||
179 | |||
180 | dapm_assert_locked(w->dapm); | ||
181 | |||
182 | if (w->inputs == -1) | ||
183 | return; | ||
184 | |||
185 | w->inputs = -1; | ||
186 | list_add_tail(&w->work_list, &list); | ||
187 | |||
188 | list_for_each_entry(w, &list, work_list) { | ||
189 | list_for_each_entry(p, &w->sinks, list_source) { | ||
190 | if (p->is_supply || p->weak || !p->connect) | ||
191 | continue; | ||
192 | sink = p->sink; | ||
193 | if (sink->inputs != -1) { | ||
194 | sink->inputs = -1; | ||
195 | list_add_tail(&sink->work_list, &list); | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * dapm_widget_invalidate_output_paths() - Invalidate the cached number of | ||
203 | * output paths | ||
204 | * @w: The widget for which to invalidate the cached number of output paths | ||
205 | * | ||
206 | * Resets the cached number of outputs for the specified widget and all widgets | ||
207 | * that can be reached via incoming paths from the widget. | ||
208 | * | ||
209 | * This function must be called if the number of output paths for a widget might | ||
210 | * have changed. E.g. if the sink state of a widget changes or a path is added | ||
211 | * or activated with the widget as the source. | ||
212 | */ | ||
213 | static void dapm_widget_invalidate_output_paths(struct snd_soc_dapm_widget *w) | ||
214 | { | ||
215 | struct snd_soc_dapm_widget *source; | ||
216 | struct snd_soc_dapm_path *p; | ||
217 | LIST_HEAD(list); | ||
218 | |||
219 | dapm_assert_locked(w->dapm); | ||
220 | |||
221 | if (w->outputs == -1) | ||
222 | return; | ||
223 | |||
224 | w->outputs = -1; | ||
225 | list_add_tail(&w->work_list, &list); | ||
226 | |||
227 | list_for_each_entry(w, &list, work_list) { | ||
228 | list_for_each_entry(p, &w->sources, list_sink) { | ||
229 | if (p->is_supply || p->weak || !p->connect) | ||
230 | continue; | ||
231 | source = p->source; | ||
232 | if (source->outputs != -1) { | ||
233 | source->outputs = -1; | ||
234 | list_add_tail(&source->work_list, &list); | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * dapm_path_invalidate() - Invalidates the cached number of inputs and outputs | ||
242 | * for the widgets connected to a path | ||
243 | * @p: The path to invalidate | ||
244 | * | ||
245 | * Resets the cached number of inputs for the sink of the path and the cached | ||
246 | * number of outputs for the source of the path. | ||
247 | * | ||
248 | * This function must be called when a path is added, removed or the connected | ||
249 | * state changes. | ||
250 | */ | ||
251 | static void dapm_path_invalidate(struct snd_soc_dapm_path *p) | ||
252 | { | ||
253 | /* | ||
254 | * Weak paths or supply paths do not influence the number of input or | ||
255 | * output paths of their neighbors. | ||
256 | */ | ||
257 | if (p->weak || p->is_supply) | ||
258 | return; | ||
259 | |||
260 | /* | ||
261 | * The number of connected endpoints is the sum of the number of | ||
262 | * connected endpoints of all neighbors. If a node with 0 connected | ||
263 | * endpoints is either connected or disconnected that sum won't change, | ||
264 | * so there is no need to re-check the path. | ||
265 | */ | ||
266 | if (p->source->inputs != 0) | ||
267 | dapm_widget_invalidate_input_paths(p->sink); | ||
268 | if (p->sink->outputs != 0) | ||
269 | dapm_widget_invalidate_output_paths(p->source); | ||
270 | } | ||
271 | |||
272 | void dapm_mark_endpoints_dirty(struct snd_soc_card *card) | ||
163 | { | 273 | { |
164 | struct snd_soc_card *card = dapm->card; | ||
165 | struct snd_soc_dapm_widget *w; | 274 | struct snd_soc_dapm_widget *w; |
166 | 275 | ||
167 | mutex_lock(&card->dapm_mutex); | 276 | mutex_lock(&card->dapm_mutex); |
168 | 277 | ||
169 | list_for_each_entry(w, &card->widgets, list) { | 278 | list_for_each_entry(w, &card->widgets, list) { |
170 | switch (w->id) { | 279 | if (w->is_sink || w->is_source) { |
171 | case snd_soc_dapm_input: | 280 | dapm_mark_dirty(w, "Rechecking endpoints"); |
172 | case snd_soc_dapm_output: | 281 | if (w->is_sink) |
173 | dapm_mark_dirty(w, "Rechecking inputs and outputs"); | 282 | dapm_widget_invalidate_output_paths(w); |
174 | break; | 283 | if (w->is_source) |
175 | default: | 284 | dapm_widget_invalidate_input_paths(w); |
176 | break; | ||
177 | } | 285 | } |
178 | } | 286 | } |
179 | 287 | ||
180 | mutex_unlock(&card->dapm_mutex); | 288 | mutex_unlock(&card->dapm_mutex); |
181 | } | 289 | } |
182 | EXPORT_SYMBOL_GPL(dapm_mark_io_dirty); | 290 | EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty); |
183 | 291 | ||
184 | /* create a new dapm widget */ | 292 | /* create a new dapm widget */ |
185 | static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | 293 | static inline struct snd_soc_dapm_widget *dapm_cnew_widget( |
@@ -386,8 +494,6 @@ static void dapm_reset(struct snd_soc_card *card) | |||
386 | list_for_each_entry(w, &card->widgets, list) { | 494 | list_for_each_entry(w, &card->widgets, list) { |
387 | w->new_power = w->power; | 495 | w->new_power = w->power; |
388 | w->power_checked = false; | 496 | w->power_checked = false; |
389 | w->inputs = -1; | ||
390 | w->outputs = -1; | ||
391 | } | 497 | } |
392 | } | 498 | } |
393 | 499 | ||
@@ -469,10 +575,9 @@ out: | |||
469 | 575 | ||
470 | /* connect mux widget to its interconnecting audio paths */ | 576 | /* connect mux widget to its interconnecting audio paths */ |
471 | static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | 577 | static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, |
472 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, | 578 | struct snd_soc_dapm_path *path, const char *control_name) |
473 | struct snd_soc_dapm_path *path, const char *control_name, | ||
474 | const struct snd_kcontrol_new *kcontrol) | ||
475 | { | 579 | { |
580 | const struct snd_kcontrol_new *kcontrol = &path->sink->kcontrol_news[0]; | ||
476 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 581 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
477 | unsigned int val, item; | 582 | unsigned int val, item; |
478 | int i; | 583 | int i; |
@@ -493,10 +598,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | |||
493 | 598 | ||
494 | for (i = 0; i < e->items; i++) { | 599 | for (i = 0; i < e->items; i++) { |
495 | if (!(strcmp(control_name, e->texts[i]))) { | 600 | if (!(strcmp(control_name, e->texts[i]))) { |
496 | list_add(&path->list, &dapm->card->paths); | 601 | path->name = e->texts[i]; |
497 | list_add(&path->list_sink, &dest->sources); | ||
498 | list_add(&path->list_source, &src->sinks); | ||
499 | path->name = (char*)e->texts[i]; | ||
500 | if (i == item) | 602 | if (i == item) |
501 | path->connect = 1; | 603 | path->connect = 1; |
502 | else | 604 | else |
@@ -509,11 +611,10 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | |||
509 | } | 611 | } |
510 | 612 | ||
511 | /* set up initial codec paths */ | 613 | /* set up initial codec paths */ |
512 | static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, | 614 | static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i) |
513 | struct snd_soc_dapm_path *p, int i) | ||
514 | { | 615 | { |
515 | struct soc_mixer_control *mc = (struct soc_mixer_control *) | 616 | struct soc_mixer_control *mc = (struct soc_mixer_control *) |
516 | w->kcontrol_news[i].private_value; | 617 | p->sink->kcontrol_news[i].private_value; |
517 | unsigned int reg = mc->reg; | 618 | unsigned int reg = mc->reg; |
518 | unsigned int shift = mc->shift; | 619 | unsigned int shift = mc->shift; |
519 | unsigned int max = mc->max; | 620 | unsigned int max = mc->max; |
@@ -522,7 +623,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, | |||
522 | unsigned int val; | 623 | unsigned int val; |
523 | 624 | ||
524 | if (reg != SND_SOC_NOPM) { | 625 | if (reg != SND_SOC_NOPM) { |
525 | soc_dapm_read(w->dapm, reg, &val); | 626 | soc_dapm_read(p->sink->dapm, reg, &val); |
526 | val = (val >> shift) & mask; | 627 | val = (val >> shift) & mask; |
527 | if (invert) | 628 | if (invert) |
528 | val = max - val; | 629 | val = max - val; |
@@ -534,19 +635,15 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, | |||
534 | 635 | ||
535 | /* connect mixer widget to its interconnecting audio paths */ | 636 | /* connect mixer widget to its interconnecting audio paths */ |
536 | static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, | 637 | static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, |
537 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, | ||
538 | struct snd_soc_dapm_path *path, const char *control_name) | 638 | struct snd_soc_dapm_path *path, const char *control_name) |
539 | { | 639 | { |
540 | int i; | 640 | int i; |
541 | 641 | ||
542 | /* search for mixer kcontrol */ | 642 | /* search for mixer kcontrol */ |
543 | for (i = 0; i < dest->num_kcontrols; i++) { | 643 | for (i = 0; i < path->sink->num_kcontrols; i++) { |
544 | if (!strcmp(control_name, dest->kcontrol_news[i].name)) { | 644 | if (!strcmp(control_name, path->sink->kcontrol_news[i].name)) { |
545 | list_add(&path->list, &dapm->card->paths); | 645 | path->name = path->sink->kcontrol_news[i].name; |
546 | list_add(&path->list_sink, &dest->sources); | 646 | dapm_set_mixer_path_status(path, i); |
547 | list_add(&path->list_source, &src->sinks); | ||
548 | path->name = dest->kcontrol_news[i].name; | ||
549 | dapm_set_mixer_path_status(dest, path, i); | ||
550 | return 0; | 647 | return 0; |
551 | } | 648 | } |
552 | } | 649 | } |
@@ -738,8 +835,10 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w) | |||
738 | if (ret < 0) | 835 | if (ret < 0) |
739 | return ret; | 836 | return ret; |
740 | 837 | ||
741 | list_for_each_entry(path, &w->sources, list_sink) | 838 | list_for_each_entry(path, &w->sources, list_sink) { |
742 | dapm_kcontrol_add_path(w->kcontrols[0], path); | 839 | if (path->name) |
840 | dapm_kcontrol_add_path(w->kcontrols[0], path); | ||
841 | } | ||
743 | 842 | ||
744 | return 0; | 843 | return 0; |
745 | } | 844 | } |
@@ -754,34 +853,6 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w) | |||
754 | return 0; | 853 | return 0; |
755 | } | 854 | } |
756 | 855 | ||
757 | /* reset 'walked' bit for each dapm path */ | ||
758 | static void dapm_clear_walk_output(struct snd_soc_dapm_context *dapm, | ||
759 | struct list_head *sink) | ||
760 | { | ||
761 | struct snd_soc_dapm_path *p; | ||
762 | |||
763 | list_for_each_entry(p, sink, list_source) { | ||
764 | if (p->walked) { | ||
765 | p->walked = 0; | ||
766 | dapm_clear_walk_output(dapm, &p->sink->sinks); | ||
767 | } | ||
768 | } | ||
769 | } | ||
770 | |||
771 | static void dapm_clear_walk_input(struct snd_soc_dapm_context *dapm, | ||
772 | struct list_head *source) | ||
773 | { | ||
774 | struct snd_soc_dapm_path *p; | ||
775 | |||
776 | list_for_each_entry(p, source, list_sink) { | ||
777 | if (p->walked) { | ||
778 | p->walked = 0; | ||
779 | dapm_clear_walk_input(dapm, &p->source->sources); | ||
780 | } | ||
781 | } | ||
782 | } | ||
783 | |||
784 | |||
785 | /* We implement power down on suspend by checking the power state of | 856 | /* We implement power down on suspend by checking the power state of |
786 | * the ALSA card - when we are suspending the ALSA state for the card | 857 | * the ALSA card - when we are suspending the ALSA state for the card |
787 | * is set to D3. | 858 | * is set to D3. |
@@ -856,61 +927,23 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, | |||
856 | 927 | ||
857 | DAPM_UPDATE_STAT(widget, path_checks); | 928 | DAPM_UPDATE_STAT(widget, path_checks); |
858 | 929 | ||
859 | switch (widget->id) { | 930 | if (widget->is_sink && widget->connected) { |
860 | case snd_soc_dapm_supply: | 931 | widget->outputs = snd_soc_dapm_suspend_check(widget); |
861 | case snd_soc_dapm_regulator_supply: | 932 | return widget->outputs; |
862 | case snd_soc_dapm_clock_supply: | ||
863 | case snd_soc_dapm_kcontrol: | ||
864 | return 0; | ||
865 | default: | ||
866 | break; | ||
867 | } | ||
868 | |||
869 | switch (widget->id) { | ||
870 | case snd_soc_dapm_adc: | ||
871 | case snd_soc_dapm_aif_out: | ||
872 | case snd_soc_dapm_dai_out: | ||
873 | if (widget->active) { | ||
874 | widget->outputs = snd_soc_dapm_suspend_check(widget); | ||
875 | return widget->outputs; | ||
876 | } | ||
877 | default: | ||
878 | break; | ||
879 | } | ||
880 | |||
881 | if (widget->connected) { | ||
882 | /* connected pin ? */ | ||
883 | if (widget->id == snd_soc_dapm_output && !widget->ext) { | ||
884 | widget->outputs = snd_soc_dapm_suspend_check(widget); | ||
885 | return widget->outputs; | ||
886 | } | ||
887 | |||
888 | /* connected jack or spk ? */ | ||
889 | if (widget->id == snd_soc_dapm_hp || | ||
890 | widget->id == snd_soc_dapm_spk || | ||
891 | (widget->id == snd_soc_dapm_line && | ||
892 | !list_empty(&widget->sources))) { | ||
893 | widget->outputs = snd_soc_dapm_suspend_check(widget); | ||
894 | return widget->outputs; | ||
895 | } | ||
896 | } | 933 | } |
897 | 934 | ||
898 | list_for_each_entry(path, &widget->sinks, list_source) { | 935 | list_for_each_entry(path, &widget->sinks, list_source) { |
899 | DAPM_UPDATE_STAT(widget, neighbour_checks); | 936 | DAPM_UPDATE_STAT(widget, neighbour_checks); |
900 | 937 | ||
901 | if (path->weak) | 938 | if (path->weak || path->is_supply) |
902 | continue; | 939 | continue; |
903 | 940 | ||
904 | if (path->walking) | 941 | if (path->walking) |
905 | return 1; | 942 | return 1; |
906 | 943 | ||
907 | if (path->walked) | ||
908 | continue; | ||
909 | |||
910 | trace_snd_soc_dapm_output_path(widget, path); | 944 | trace_snd_soc_dapm_output_path(widget, path); |
911 | 945 | ||
912 | if (path->sink && path->connect) { | 946 | if (path->connect) { |
913 | path->walked = 1; | ||
914 | path->walking = 1; | 947 | path->walking = 1; |
915 | 948 | ||
916 | /* do we need to add this widget to the list ? */ | 949 | /* do we need to add this widget to the list ? */ |
@@ -952,73 +985,23 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, | |||
952 | 985 | ||
953 | DAPM_UPDATE_STAT(widget, path_checks); | 986 | DAPM_UPDATE_STAT(widget, path_checks); |
954 | 987 | ||
955 | switch (widget->id) { | 988 | if (widget->is_source && widget->connected) { |
956 | case snd_soc_dapm_supply: | 989 | widget->inputs = snd_soc_dapm_suspend_check(widget); |
957 | case snd_soc_dapm_regulator_supply: | 990 | return widget->inputs; |
958 | case snd_soc_dapm_clock_supply: | ||
959 | case snd_soc_dapm_kcontrol: | ||
960 | return 0; | ||
961 | default: | ||
962 | break; | ||
963 | } | ||
964 | |||
965 | /* active stream ? */ | ||
966 | switch (widget->id) { | ||
967 | case snd_soc_dapm_dac: | ||
968 | case snd_soc_dapm_aif_in: | ||
969 | case snd_soc_dapm_dai_in: | ||
970 | if (widget->active) { | ||
971 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
972 | return widget->inputs; | ||
973 | } | ||
974 | default: | ||
975 | break; | ||
976 | } | ||
977 | |||
978 | if (widget->connected) { | ||
979 | /* connected pin ? */ | ||
980 | if (widget->id == snd_soc_dapm_input && !widget->ext) { | ||
981 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
982 | return widget->inputs; | ||
983 | } | ||
984 | |||
985 | /* connected VMID/Bias for lower pops */ | ||
986 | if (widget->id == snd_soc_dapm_vmid) { | ||
987 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
988 | return widget->inputs; | ||
989 | } | ||
990 | |||
991 | /* connected jack ? */ | ||
992 | if (widget->id == snd_soc_dapm_mic || | ||
993 | (widget->id == snd_soc_dapm_line && | ||
994 | !list_empty(&widget->sinks))) { | ||
995 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
996 | return widget->inputs; | ||
997 | } | ||
998 | |||
999 | /* signal generator */ | ||
1000 | if (widget->id == snd_soc_dapm_siggen) { | ||
1001 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
1002 | return widget->inputs; | ||
1003 | } | ||
1004 | } | 991 | } |
1005 | 992 | ||
1006 | list_for_each_entry(path, &widget->sources, list_sink) { | 993 | list_for_each_entry(path, &widget->sources, list_sink) { |
1007 | DAPM_UPDATE_STAT(widget, neighbour_checks); | 994 | DAPM_UPDATE_STAT(widget, neighbour_checks); |
1008 | 995 | ||
1009 | if (path->weak) | 996 | if (path->weak || path->is_supply) |
1010 | continue; | 997 | continue; |
1011 | 998 | ||
1012 | if (path->walking) | 999 | if (path->walking) |
1013 | return 1; | 1000 | return 1; |
1014 | 1001 | ||
1015 | if (path->walked) | ||
1016 | continue; | ||
1017 | |||
1018 | trace_snd_soc_dapm_input_path(widget, path); | 1002 | trace_snd_soc_dapm_input_path(widget, path); |
1019 | 1003 | ||
1020 | if (path->source && path->connect) { | 1004 | if (path->connect) { |
1021 | path->walked = 1; | ||
1022 | path->walking = 1; | 1005 | path->walking = 1; |
1023 | 1006 | ||
1024 | /* do we need to add this widget to the list ? */ | 1007 | /* do we need to add this widget to the list ? */ |
@@ -1060,21 +1043,25 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, | |||
1060 | int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, | 1043 | int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, |
1061 | struct snd_soc_dapm_widget_list **list) | 1044 | struct snd_soc_dapm_widget_list **list) |
1062 | { | 1045 | { |
1063 | struct snd_soc_card *card = dai->card; | 1046 | struct snd_soc_card *card = dai->component->card; |
1047 | struct snd_soc_dapm_widget *w; | ||
1064 | int paths; | 1048 | int paths; |
1065 | 1049 | ||
1066 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 1050 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
1067 | dapm_reset(card); | ||
1068 | 1051 | ||
1069 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1052 | /* |
1053 | * For is_connected_{output,input}_ep fully discover the graph we need | ||
1054 | * to reset the cached number of inputs and outputs. | ||
1055 | */ | ||
1056 | list_for_each_entry(w, &card->widgets, list) { | ||
1057 | w->inputs = -1; | ||
1058 | w->outputs = -1; | ||
1059 | } | ||
1060 | |||
1061 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
1070 | paths = is_connected_output_ep(dai->playback_widget, list); | 1062 | paths = is_connected_output_ep(dai->playback_widget, list); |
1071 | dapm_clear_walk_output(&card->dapm, | 1063 | else |
1072 | &dai->playback_widget->sinks); | ||
1073 | } else { | ||
1074 | paths = is_connected_input_ep(dai->capture_widget, list); | 1064 | paths = is_connected_input_ep(dai->capture_widget, list); |
1075 | dapm_clear_walk_input(&card->dapm, | ||
1076 | &dai->capture_widget->sources); | ||
1077 | } | ||
1078 | 1065 | ||
1079 | trace_snd_soc_dapm_connected(paths, stream); | 1066 | trace_snd_soc_dapm_connected(paths, stream); |
1080 | mutex_unlock(&card->dapm_mutex); | 1067 | mutex_unlock(&card->dapm_mutex); |
@@ -1163,44 +1150,10 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w) | |||
1163 | DAPM_UPDATE_STAT(w, power_checks); | 1150 | DAPM_UPDATE_STAT(w, power_checks); |
1164 | 1151 | ||
1165 | in = is_connected_input_ep(w, NULL); | 1152 | in = is_connected_input_ep(w, NULL); |
1166 | dapm_clear_walk_input(w->dapm, &w->sources); | ||
1167 | out = is_connected_output_ep(w, NULL); | 1153 | out = is_connected_output_ep(w, NULL); |
1168 | dapm_clear_walk_output(w->dapm, &w->sinks); | ||
1169 | return out != 0 && in != 0; | 1154 | return out != 0 && in != 0; |
1170 | } | 1155 | } |
1171 | 1156 | ||
1172 | /* Check to see if an ADC has power */ | ||
1173 | static int dapm_adc_check_power(struct snd_soc_dapm_widget *w) | ||
1174 | { | ||
1175 | int in; | ||
1176 | |||
1177 | DAPM_UPDATE_STAT(w, power_checks); | ||
1178 | |||
1179 | if (w->active) { | ||
1180 | in = is_connected_input_ep(w, NULL); | ||
1181 | dapm_clear_walk_input(w->dapm, &w->sources); | ||
1182 | return in != 0; | ||
1183 | } else { | ||
1184 | return dapm_generic_check_power(w); | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | /* Check to see if a DAC has power */ | ||
1189 | static int dapm_dac_check_power(struct snd_soc_dapm_widget *w) | ||
1190 | { | ||
1191 | int out; | ||
1192 | |||
1193 | DAPM_UPDATE_STAT(w, power_checks); | ||
1194 | |||
1195 | if (w->active) { | ||
1196 | out = is_connected_output_ep(w, NULL); | ||
1197 | dapm_clear_walk_output(w->dapm, &w->sinks); | ||
1198 | return out != 0; | ||
1199 | } else { | ||
1200 | return dapm_generic_check_power(w); | ||
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | /* Check to see if a power supply is needed */ | 1157 | /* Check to see if a power supply is needed */ |
1205 | static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | 1158 | static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) |
1206 | { | 1159 | { |
@@ -1219,9 +1172,6 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | |||
1219 | !path->connected(path->source, path->sink)) | 1172 | !path->connected(path->source, path->sink)) |
1220 | continue; | 1173 | continue; |
1221 | 1174 | ||
1222 | if (!path->sink) | ||
1223 | continue; | ||
1224 | |||
1225 | if (dapm_widget_power_check(path->sink)) | 1175 | if (dapm_widget_power_check(path->sink)) |
1226 | return 1; | 1176 | return 1; |
1227 | } | 1177 | } |
@@ -1636,27 +1586,14 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power, | |||
1636 | /* If we changed our power state perhaps our neigbours changed | 1586 | /* If we changed our power state perhaps our neigbours changed |
1637 | * also. | 1587 | * also. |
1638 | */ | 1588 | */ |
1639 | list_for_each_entry(path, &w->sources, list_sink) { | 1589 | list_for_each_entry(path, &w->sources, list_sink) |
1640 | if (path->source) { | 1590 | dapm_widget_set_peer_power(path->source, power, path->connect); |
1641 | dapm_widget_set_peer_power(path->source, power, | 1591 | |
1592 | /* Supplies can't affect their outputs, only their inputs */ | ||
1593 | if (!w->is_supply) { | ||
1594 | list_for_each_entry(path, &w->sinks, list_source) | ||
1595 | dapm_widget_set_peer_power(path->sink, power, | ||
1642 | path->connect); | 1596 | path->connect); |
1643 | } | ||
1644 | } | ||
1645 | switch (w->id) { | ||
1646 | case snd_soc_dapm_supply: | ||
1647 | case snd_soc_dapm_regulator_supply: | ||
1648 | case snd_soc_dapm_clock_supply: | ||
1649 | case snd_soc_dapm_kcontrol: | ||
1650 | /* Supplies can't affect their outputs, only their inputs */ | ||
1651 | break; | ||
1652 | default: | ||
1653 | list_for_each_entry(path, &w->sinks, list_source) { | ||
1654 | if (path->sink) { | ||
1655 | dapm_widget_set_peer_power(path->sink, power, | ||
1656 | path->connect); | ||
1657 | } | ||
1658 | } | ||
1659 | break; | ||
1660 | } | 1597 | } |
1661 | 1598 | ||
1662 | if (power) | 1599 | if (power) |
@@ -1863,10 +1800,14 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
1863 | if (!buf) | 1800 | if (!buf) |
1864 | return -ENOMEM; | 1801 | return -ENOMEM; |
1865 | 1802 | ||
1866 | in = is_connected_input_ep(w, NULL); | 1803 | /* Supply widgets are not handled by is_connected_{input,output}_ep() */ |
1867 | dapm_clear_walk_input(w->dapm, &w->sources); | 1804 | if (w->is_supply) { |
1868 | out = is_connected_output_ep(w, NULL); | 1805 | in = 0; |
1869 | dapm_clear_walk_output(w->dapm, &w->sinks); | 1806 | out = 0; |
1807 | } else { | ||
1808 | in = is_connected_input_ep(w, NULL); | ||
1809 | out = is_connected_output_ep(w, NULL); | ||
1810 | } | ||
1870 | 1811 | ||
1871 | ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d", | 1812 | ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d", |
1872 | w->name, w->power ? "On" : "Off", | 1813 | w->name, w->power ? "On" : "Off", |
@@ -2011,32 +1952,45 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) | |||
2011 | 1952 | ||
2012 | #endif | 1953 | #endif |
2013 | 1954 | ||
1955 | /* | ||
1956 | * soc_dapm_connect_path() - Connects or disconnects a path | ||
1957 | * @path: The path to update | ||
1958 | * @connect: The new connect state of the path. True if the path is connected, | ||
1959 | * false if it is disconneted. | ||
1960 | * @reason: The reason why the path changed (for debugging only) | ||
1961 | */ | ||
1962 | static void soc_dapm_connect_path(struct snd_soc_dapm_path *path, | ||
1963 | bool connect, const char *reason) | ||
1964 | { | ||
1965 | if (path->connect == connect) | ||
1966 | return; | ||
1967 | |||
1968 | path->connect = connect; | ||
1969 | dapm_mark_dirty(path->source, reason); | ||
1970 | dapm_mark_dirty(path->sink, reason); | ||
1971 | dapm_path_invalidate(path); | ||
1972 | } | ||
1973 | |||
2014 | /* test and update the power status of a mux widget */ | 1974 | /* test and update the power status of a mux widget */ |
2015 | static int soc_dapm_mux_update_power(struct snd_soc_card *card, | 1975 | static int soc_dapm_mux_update_power(struct snd_soc_card *card, |
2016 | struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) | 1976 | struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) |
2017 | { | 1977 | { |
2018 | struct snd_soc_dapm_path *path; | 1978 | struct snd_soc_dapm_path *path; |
2019 | int found = 0; | 1979 | int found = 0; |
1980 | bool connect; | ||
2020 | 1981 | ||
2021 | lockdep_assert_held(&card->dapm_mutex); | 1982 | lockdep_assert_held(&card->dapm_mutex); |
2022 | 1983 | ||
2023 | /* find dapm widget path assoc with kcontrol */ | 1984 | /* find dapm widget path assoc with kcontrol */ |
2024 | dapm_kcontrol_for_each_path(path, kcontrol) { | 1985 | dapm_kcontrol_for_each_path(path, kcontrol) { |
2025 | if (!path->name || !e->texts[mux]) | ||
2026 | continue; | ||
2027 | |||
2028 | found = 1; | 1986 | found = 1; |
2029 | /* we now need to match the string in the enum to the path */ | 1987 | /* we now need to match the string in the enum to the path */ |
2030 | if (!(strcmp(path->name, e->texts[mux]))) { | 1988 | if (!(strcmp(path->name, e->texts[mux]))) |
2031 | path->connect = 1; /* new connection */ | 1989 | connect = true; |
2032 | dapm_mark_dirty(path->source, "mux connection"); | 1990 | else |
2033 | } else { | 1991 | connect = false; |
2034 | if (path->connect) | 1992 | |
2035 | dapm_mark_dirty(path->source, | 1993 | soc_dapm_connect_path(path, connect, "mux update"); |
2036 | "mux disconnection"); | ||
2037 | path->connect = 0; /* old connection must be powered down */ | ||
2038 | } | ||
2039 | dapm_mark_dirty(path->sink, "mux change"); | ||
2040 | } | 1994 | } |
2041 | 1995 | ||
2042 | if (found) | 1996 | if (found) |
@@ -2075,9 +2029,7 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, | |||
2075 | /* find dapm widget path assoc with kcontrol */ | 2029 | /* find dapm widget path assoc with kcontrol */ |
2076 | dapm_kcontrol_for_each_path(path, kcontrol) { | 2030 | dapm_kcontrol_for_each_path(path, kcontrol) { |
2077 | found = 1; | 2031 | found = 1; |
2078 | path->connect = connect; | 2032 | soc_dapm_connect_path(path, connect, "mixer update"); |
2079 | dapm_mark_dirty(path->source, "mixer connection"); | ||
2080 | dapm_mark_dirty(path->sink, "mixer update"); | ||
2081 | } | 2033 | } |
2082 | 2034 | ||
2083 | if (found) | 2035 | if (found) |
@@ -2255,8 +2207,11 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, | |||
2255 | return -EINVAL; | 2207 | return -EINVAL; |
2256 | } | 2208 | } |
2257 | 2209 | ||
2258 | if (w->connected != status) | 2210 | if (w->connected != status) { |
2259 | dapm_mark_dirty(w, "pin configuration"); | 2211 | dapm_mark_dirty(w, "pin configuration"); |
2212 | dapm_widget_invalidate_input_paths(w); | ||
2213 | dapm_widget_invalidate_output_paths(w); | ||
2214 | } | ||
2260 | 2215 | ||
2261 | w->connected = status; | 2216 | w->connected = status; |
2262 | if (status == 0) | 2217 | if (status == 0) |
@@ -2309,6 +2264,53 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) | |||
2309 | } | 2264 | } |
2310 | EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); | 2265 | EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); |
2311 | 2266 | ||
2267 | /* | ||
2268 | * dapm_update_widget_flags() - Re-compute widget sink and source flags | ||
2269 | * @w: The widget for which to update the flags | ||
2270 | * | ||
2271 | * Some widgets have a dynamic category which depends on which neighbors they | ||
2272 | * are connected to. This function update the category for these widgets. | ||
2273 | * | ||
2274 | * This function must be called whenever a path is added or removed to a widget. | ||
2275 | */ | ||
2276 | static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w) | ||
2277 | { | ||
2278 | struct snd_soc_dapm_path *p; | ||
2279 | |||
2280 | switch (w->id) { | ||
2281 | case snd_soc_dapm_input: | ||
2282 | w->is_source = 1; | ||
2283 | list_for_each_entry(p, &w->sources, list_sink) { | ||
2284 | if (p->source->id == snd_soc_dapm_micbias || | ||
2285 | p->source->id == snd_soc_dapm_mic || | ||
2286 | p->source->id == snd_soc_dapm_line || | ||
2287 | p->source->id == snd_soc_dapm_output) { | ||
2288 | w->is_source = 0; | ||
2289 | break; | ||
2290 | } | ||
2291 | } | ||
2292 | break; | ||
2293 | case snd_soc_dapm_output: | ||
2294 | w->is_sink = 1; | ||
2295 | list_for_each_entry(p, &w->sinks, list_source) { | ||
2296 | if (p->sink->id == snd_soc_dapm_spk || | ||
2297 | p->sink->id == snd_soc_dapm_hp || | ||
2298 | p->sink->id == snd_soc_dapm_line || | ||
2299 | p->sink->id == snd_soc_dapm_input) { | ||
2300 | w->is_sink = 0; | ||
2301 | break; | ||
2302 | } | ||
2303 | } | ||
2304 | break; | ||
2305 | case snd_soc_dapm_line: | ||
2306 | w->is_sink = !list_empty(&w->sources); | ||
2307 | w->is_source = !list_empty(&w->sinks); | ||
2308 | break; | ||
2309 | default: | ||
2310 | break; | ||
2311 | } | ||
2312 | } | ||
2313 | |||
2312 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | 2314 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, |
2313 | struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, | 2315 | struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, |
2314 | const char *control, | 2316 | const char *control, |
@@ -2318,6 +2320,27 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2318 | struct snd_soc_dapm_path *path; | 2320 | struct snd_soc_dapm_path *path; |
2319 | int ret; | 2321 | int ret; |
2320 | 2322 | ||
2323 | if (wsink->is_supply && !wsource->is_supply) { | ||
2324 | dev_err(dapm->dev, | ||
2325 | "Connecting non-supply widget to supply widget is not supported (%s -> %s)\n", | ||
2326 | wsource->name, wsink->name); | ||
2327 | return -EINVAL; | ||
2328 | } | ||
2329 | |||
2330 | if (connected && !wsource->is_supply) { | ||
2331 | dev_err(dapm->dev, | ||
2332 | "connected() callback only supported for supply widgets (%s -> %s)\n", | ||
2333 | wsource->name, wsink->name); | ||
2334 | return -EINVAL; | ||
2335 | } | ||
2336 | |||
2337 | if (wsource->is_supply && control) { | ||
2338 | dev_err(dapm->dev, | ||
2339 | "Conditional paths are not supported for supply widgets (%s -> [%s] -> %s)\n", | ||
2340 | wsource->name, control, wsink->name); | ||
2341 | return -EINVAL; | ||
2342 | } | ||
2343 | |||
2321 | path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); | 2344 | path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); |
2322 | if (!path) | 2345 | if (!path) |
2323 | return -ENOMEM; | 2346 | return -ENOMEM; |
@@ -2330,85 +2353,49 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2330 | INIT_LIST_HEAD(&path->list_source); | 2353 | INIT_LIST_HEAD(&path->list_source); |
2331 | INIT_LIST_HEAD(&path->list_sink); | 2354 | INIT_LIST_HEAD(&path->list_sink); |
2332 | 2355 | ||
2333 | /* check for external widgets */ | 2356 | if (wsource->is_supply || wsink->is_supply) |
2334 | if (wsink->id == snd_soc_dapm_input) { | 2357 | path->is_supply = 1; |
2335 | if (wsource->id == snd_soc_dapm_micbias || | ||
2336 | wsource->id == snd_soc_dapm_mic || | ||
2337 | wsource->id == snd_soc_dapm_line || | ||
2338 | wsource->id == snd_soc_dapm_output) | ||
2339 | wsink->ext = 1; | ||
2340 | } | ||
2341 | if (wsource->id == snd_soc_dapm_output) { | ||
2342 | if (wsink->id == snd_soc_dapm_spk || | ||
2343 | wsink->id == snd_soc_dapm_hp || | ||
2344 | wsink->id == snd_soc_dapm_line || | ||
2345 | wsink->id == snd_soc_dapm_input) | ||
2346 | wsource->ext = 1; | ||
2347 | } | ||
2348 | |||
2349 | dapm_mark_dirty(wsource, "Route added"); | ||
2350 | dapm_mark_dirty(wsink, "Route added"); | ||
2351 | 2358 | ||
2352 | /* connect static paths */ | 2359 | /* connect static paths */ |
2353 | if (control == NULL) { | 2360 | if (control == NULL) { |
2354 | list_add(&path->list, &dapm->card->paths); | ||
2355 | list_add(&path->list_sink, &wsink->sources); | ||
2356 | list_add(&path->list_source, &wsource->sinks); | ||
2357 | path->connect = 1; | 2361 | path->connect = 1; |
2358 | return 0; | 2362 | } else { |
2359 | } | 2363 | /* connect dynamic paths */ |
2360 | 2364 | switch (wsink->id) { | |
2361 | /* connect dynamic paths */ | 2365 | case snd_soc_dapm_mux: |
2362 | switch (wsink->id) { | 2366 | ret = dapm_connect_mux(dapm, path, control); |
2363 | case snd_soc_dapm_adc: | 2367 | if (ret != 0) |
2364 | case snd_soc_dapm_dac: | 2368 | goto err; |
2365 | case snd_soc_dapm_pga: | 2369 | break; |
2366 | case snd_soc_dapm_out_drv: | 2370 | case snd_soc_dapm_switch: |
2367 | case snd_soc_dapm_input: | 2371 | case snd_soc_dapm_mixer: |
2368 | case snd_soc_dapm_output: | 2372 | case snd_soc_dapm_mixer_named_ctl: |
2369 | case snd_soc_dapm_siggen: | 2373 | ret = dapm_connect_mixer(dapm, path, control); |
2370 | case snd_soc_dapm_micbias: | 2374 | if (ret != 0) |
2371 | case snd_soc_dapm_vmid: | 2375 | goto err; |
2372 | case snd_soc_dapm_pre: | 2376 | break; |
2373 | case snd_soc_dapm_post: | 2377 | default: |
2374 | case snd_soc_dapm_supply: | 2378 | dev_err(dapm->dev, |
2375 | case snd_soc_dapm_regulator_supply: | 2379 | "Control not supported for path %s -> [%s] -> %s\n", |
2376 | case snd_soc_dapm_clock_supply: | 2380 | wsource->name, control, wsink->name); |
2377 | case snd_soc_dapm_aif_in: | 2381 | ret = -EINVAL; |
2378 | case snd_soc_dapm_aif_out: | ||
2379 | case snd_soc_dapm_dai_in: | ||
2380 | case snd_soc_dapm_dai_out: | ||
2381 | case snd_soc_dapm_dai_link: | ||
2382 | case snd_soc_dapm_kcontrol: | ||
2383 | list_add(&path->list, &dapm->card->paths); | ||
2384 | list_add(&path->list_sink, &wsink->sources); | ||
2385 | list_add(&path->list_source, &wsource->sinks); | ||
2386 | path->connect = 1; | ||
2387 | return 0; | ||
2388 | case snd_soc_dapm_mux: | ||
2389 | ret = dapm_connect_mux(dapm, wsource, wsink, path, control, | ||
2390 | &wsink->kcontrol_news[0]); | ||
2391 | if (ret != 0) | ||
2392 | goto err; | ||
2393 | break; | ||
2394 | case snd_soc_dapm_switch: | ||
2395 | case snd_soc_dapm_mixer: | ||
2396 | case snd_soc_dapm_mixer_named_ctl: | ||
2397 | ret = dapm_connect_mixer(dapm, wsource, wsink, path, control); | ||
2398 | if (ret != 0) | ||
2399 | goto err; | 2382 | goto err; |
2400 | break; | 2383 | } |
2401 | case snd_soc_dapm_hp: | ||
2402 | case snd_soc_dapm_mic: | ||
2403 | case snd_soc_dapm_line: | ||
2404 | case snd_soc_dapm_spk: | ||
2405 | list_add(&path->list, &dapm->card->paths); | ||
2406 | list_add(&path->list_sink, &wsink->sources); | ||
2407 | list_add(&path->list_source, &wsource->sinks); | ||
2408 | path->connect = 0; | ||
2409 | return 0; | ||
2410 | } | 2384 | } |
2411 | 2385 | ||
2386 | list_add(&path->list, &dapm->card->paths); | ||
2387 | list_add(&path->list_sink, &wsink->sources); | ||
2388 | list_add(&path->list_source, &wsource->sinks); | ||
2389 | |||
2390 | dapm_update_widget_flags(wsource); | ||
2391 | dapm_update_widget_flags(wsink); | ||
2392 | |||
2393 | dapm_mark_dirty(wsource, "Route added"); | ||
2394 | dapm_mark_dirty(wsink, "Route added"); | ||
2395 | |||
2396 | if (dapm->card->instantiated && path->connect) | ||
2397 | dapm_path_invalidate(path); | ||
2398 | |||
2412 | return 0; | 2399 | return 0; |
2413 | err: | 2400 | err: |
2414 | kfree(path); | 2401 | kfree(path); |
@@ -2489,6 +2476,7 @@ err: | |||
2489 | static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | 2476 | static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, |
2490 | const struct snd_soc_dapm_route *route) | 2477 | const struct snd_soc_dapm_route *route) |
2491 | { | 2478 | { |
2479 | struct snd_soc_dapm_widget *wsource, *wsink; | ||
2492 | struct snd_soc_dapm_path *path, *p; | 2480 | struct snd_soc_dapm_path *path, *p; |
2493 | const char *sink; | 2481 | const char *sink; |
2494 | const char *source; | 2482 | const char *source; |
@@ -2526,10 +2514,19 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | |||
2526 | } | 2514 | } |
2527 | 2515 | ||
2528 | if (path) { | 2516 | if (path) { |
2529 | dapm_mark_dirty(path->source, "Route removed"); | 2517 | wsource = path->source; |
2530 | dapm_mark_dirty(path->sink, "Route removed"); | 2518 | wsink = path->sink; |
2519 | |||
2520 | dapm_mark_dirty(wsource, "Route removed"); | ||
2521 | dapm_mark_dirty(wsink, "Route removed"); | ||
2522 | if (path->connect) | ||
2523 | dapm_path_invalidate(path); | ||
2531 | 2524 | ||
2532 | dapm_free_path(path); | 2525 | dapm_free_path(path); |
2526 | |||
2527 | /* Update any path related flags */ | ||
2528 | dapm_update_widget_flags(wsource); | ||
2529 | dapm_update_widget_flags(wsink); | ||
2533 | } else { | 2530 | } else { |
2534 | dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n", | 2531 | dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n", |
2535 | source, sink); | 2532 | source, sink); |
@@ -3087,40 +3084,44 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3087 | } | 3084 | } |
3088 | 3085 | ||
3089 | switch (w->id) { | 3086 | switch (w->id) { |
3090 | case snd_soc_dapm_switch: | 3087 | case snd_soc_dapm_mic: |
3091 | case snd_soc_dapm_mixer: | 3088 | case snd_soc_dapm_input: |
3092 | case snd_soc_dapm_mixer_named_ctl: | 3089 | w->is_source = 1; |
3093 | w->power_check = dapm_generic_check_power; | 3090 | w->power_check = dapm_generic_check_power; |
3094 | break; | 3091 | break; |
3095 | case snd_soc_dapm_mux: | 3092 | case snd_soc_dapm_spk: |
3093 | case snd_soc_dapm_hp: | ||
3094 | case snd_soc_dapm_output: | ||
3095 | w->is_sink = 1; | ||
3096 | w->power_check = dapm_generic_check_power; | 3096 | w->power_check = dapm_generic_check_power; |
3097 | break; | 3097 | break; |
3098 | case snd_soc_dapm_dai_out: | 3098 | case snd_soc_dapm_vmid: |
3099 | w->power_check = dapm_adc_check_power; | 3099 | case snd_soc_dapm_siggen: |
3100 | break; | 3100 | w->is_source = 1; |
3101 | case snd_soc_dapm_dai_in: | 3101 | w->power_check = dapm_always_on_check_power; |
3102 | w->power_check = dapm_dac_check_power; | ||
3103 | break; | 3102 | break; |
3103 | case snd_soc_dapm_mux: | ||
3104 | case snd_soc_dapm_switch: | ||
3105 | case snd_soc_dapm_mixer: | ||
3106 | case snd_soc_dapm_mixer_named_ctl: | ||
3104 | case snd_soc_dapm_adc: | 3107 | case snd_soc_dapm_adc: |
3105 | case snd_soc_dapm_aif_out: | 3108 | case snd_soc_dapm_aif_out: |
3106 | case snd_soc_dapm_dac: | 3109 | case snd_soc_dapm_dac: |
3107 | case snd_soc_dapm_aif_in: | 3110 | case snd_soc_dapm_aif_in: |
3108 | case snd_soc_dapm_pga: | 3111 | case snd_soc_dapm_pga: |
3109 | case snd_soc_dapm_out_drv: | 3112 | case snd_soc_dapm_out_drv: |
3110 | case snd_soc_dapm_input: | ||
3111 | case snd_soc_dapm_output: | ||
3112 | case snd_soc_dapm_micbias: | 3113 | case snd_soc_dapm_micbias: |
3113 | case snd_soc_dapm_spk: | ||
3114 | case snd_soc_dapm_hp: | ||
3115 | case snd_soc_dapm_mic: | ||
3116 | case snd_soc_dapm_line: | 3114 | case snd_soc_dapm_line: |
3117 | case snd_soc_dapm_dai_link: | 3115 | case snd_soc_dapm_dai_link: |
3116 | case snd_soc_dapm_dai_out: | ||
3117 | case snd_soc_dapm_dai_in: | ||
3118 | w->power_check = dapm_generic_check_power; | 3118 | w->power_check = dapm_generic_check_power; |
3119 | break; | 3119 | break; |
3120 | case snd_soc_dapm_supply: | 3120 | case snd_soc_dapm_supply: |
3121 | case snd_soc_dapm_regulator_supply: | 3121 | case snd_soc_dapm_regulator_supply: |
3122 | case snd_soc_dapm_clock_supply: | 3122 | case snd_soc_dapm_clock_supply: |
3123 | case snd_soc_dapm_kcontrol: | 3123 | case snd_soc_dapm_kcontrol: |
3124 | w->is_supply = 1; | ||
3124 | w->power_check = dapm_supply_check_power; | 3125 | w->power_check = dapm_supply_check_power; |
3125 | break; | 3126 | break; |
3126 | default: | 3127 | default: |
@@ -3137,6 +3138,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3137 | INIT_LIST_HEAD(&w->dirty); | 3138 | INIT_LIST_HEAD(&w->dirty); |
3138 | list_add(&w->list, &dapm->card->widgets); | 3139 | list_add(&w->list, &dapm->card->widgets); |
3139 | 3140 | ||
3141 | w->inputs = -1; | ||
3142 | w->outputs = -1; | ||
3143 | |||
3140 | /* machine layer set ups unconnected pins and insertions */ | 3144 | /* machine layer set ups unconnected pins and insertions */ |
3141 | w->connected = 1; | 3145 | w->connected = 1; |
3142 | return w; | 3146 | return w; |
@@ -3484,6 +3488,14 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, | |||
3484 | case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: | 3488 | case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: |
3485 | break; | 3489 | break; |
3486 | } | 3490 | } |
3491 | |||
3492 | if (w->id == snd_soc_dapm_dai_in) { | ||
3493 | w->is_source = w->active; | ||
3494 | dapm_widget_invalidate_input_paths(w); | ||
3495 | } else { | ||
3496 | w->is_sink = w->active; | ||
3497 | dapm_widget_invalidate_output_paths(w); | ||
3498 | } | ||
3487 | } | 3499 | } |
3488 | } | 3500 | } |
3489 | 3501 | ||
@@ -3610,7 +3622,15 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, | |||
3610 | } | 3622 | } |
3611 | 3623 | ||
3612 | dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin); | 3624 | dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin); |
3613 | w->connected = 1; | 3625 | if (!w->connected) { |
3626 | /* | ||
3627 | * w->force does not affect the number of input or output paths, | ||
3628 | * so we only have to recheck if w->connected is changed | ||
3629 | */ | ||
3630 | dapm_widget_invalidate_input_paths(w); | ||
3631 | dapm_widget_invalidate_output_paths(w); | ||
3632 | w->connected = 1; | ||
3633 | } | ||
3614 | w->force = 1; | 3634 | w->force = 1; |
3615 | dapm_mark_dirty(w, "force enable"); | 3635 | dapm_mark_dirty(w, "force enable"); |
3616 | 3636 | ||
@@ -3788,35 +3808,54 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, | |||
3788 | } | 3808 | } |
3789 | EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); | 3809 | EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); |
3790 | 3810 | ||
3811 | /** | ||
3812 | * dapm_is_external_path() - Checks if a path is a external path | ||
3813 | * @card: The card the path belongs to | ||
3814 | * @path: The path to check | ||
3815 | * | ||
3816 | * Returns true if the path is either between two different DAPM contexts or | ||
3817 | * between two external pins of the same DAPM context. Otherwise returns | ||
3818 | * false. | ||
3819 | */ | ||
3820 | static bool dapm_is_external_path(struct snd_soc_card *card, | ||
3821 | struct snd_soc_dapm_path *path) | ||
3822 | { | ||
3823 | dev_dbg(card->dev, | ||
3824 | "... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n", | ||
3825 | path->source->name, path->source->id, path->source->dapm, | ||
3826 | path->sink->name, path->sink->id, path->sink->dapm); | ||
3827 | |||
3828 | /* Connection between two different DAPM contexts */ | ||
3829 | if (path->source->dapm != path->sink->dapm) | ||
3830 | return true; | ||
3831 | |||
3832 | /* Loopback connection from external pin to external pin */ | ||
3833 | if (path->sink->id == snd_soc_dapm_input) { | ||
3834 | switch (path->source->id) { | ||
3835 | case snd_soc_dapm_output: | ||
3836 | case snd_soc_dapm_micbias: | ||
3837 | return true; | ||
3838 | default: | ||
3839 | break; | ||
3840 | } | ||
3841 | } | ||
3842 | |||
3843 | return false; | ||
3844 | } | ||
3845 | |||
3791 | static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card, | 3846 | static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card, |
3792 | struct snd_soc_dapm_widget *w) | 3847 | struct snd_soc_dapm_widget *w) |
3793 | { | 3848 | { |
3794 | struct snd_soc_dapm_path *p; | 3849 | struct snd_soc_dapm_path *p; |
3795 | 3850 | ||
3796 | list_for_each_entry(p, &card->paths, list) { | 3851 | list_for_each_entry(p, &w->sources, list_sink) { |
3797 | if ((p->source == w) || (p->sink == w)) { | 3852 | if (dapm_is_external_path(card, p)) |
3798 | dev_dbg(card->dev, | 3853 | return true; |
3799 | "... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n", | 3854 | } |
3800 | p->source->name, p->source->id, p->source->dapm, | ||
3801 | p->sink->name, p->sink->id, p->sink->dapm); | ||
3802 | 3855 | ||
3803 | /* Connected to something other than the codec */ | 3856 | list_for_each_entry(p, &w->sinks, list_source) { |
3804 | if (p->source->dapm != p->sink->dapm) | 3857 | if (dapm_is_external_path(card, p)) |
3805 | return true; | 3858 | return true; |
3806 | /* | ||
3807 | * Loopback connection from codec external pin to | ||
3808 | * codec external pin | ||
3809 | */ | ||
3810 | if (p->sink->id == snd_soc_dapm_input) { | ||
3811 | switch (p->source->id) { | ||
3812 | case snd_soc_dapm_output: | ||
3813 | case snd_soc_dapm_micbias: | ||
3814 | return true; | ||
3815 | default: | ||
3816 | break; | ||
3817 | } | ||
3818 | } | ||
3819 | } | ||
3820 | } | 3859 | } |
3821 | 3860 | ||
3822 | return false; | 3861 | return false; |
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c new file mode 100644 index 000000000000..100d92b5b77e --- /dev/null +++ b/sound/soc/soc-ops.c | |||
@@ -0,0 +1,952 @@ | |||
1 | /* | ||
2 | * soc-ops.c -- Generic ASoC operations | ||
3 | * | ||
4 | * Copyright 2005 Wolfson Microelectronics PLC. | ||
5 | * Copyright 2005 Openedhand Ltd. | ||
6 | * Copyright (C) 2010 Slimlogic Ltd. | ||
7 | * Copyright (C) 2010 Texas Instruments Inc. | ||
8 | * | ||
9 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> | ||
10 | * with code, comments and ideas from :- | ||
11 | * Richard Purdie <richard@openedhand.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/moduleparam.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/pm.h> | ||
24 | #include <linux/bitops.h> | ||
25 | #include <linux/ctype.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <sound/core.h> | ||
28 | #include <sound/jack.h> | ||
29 | #include <sound/pcm.h> | ||
30 | #include <sound/pcm_params.h> | ||
31 | #include <sound/soc.h> | ||
32 | #include <sound/soc-dpcm.h> | ||
33 | #include <sound/initval.h> | ||
34 | |||
35 | /** | ||
36 | * snd_soc_info_enum_double - enumerated double mixer info callback | ||
37 | * @kcontrol: mixer control | ||
38 | * @uinfo: control element information | ||
39 | * | ||
40 | * Callback to provide information about a double enumerated | ||
41 | * mixer control. | ||
42 | * | ||
43 | * Returns 0 for success. | ||
44 | */ | ||
45 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | ||
46 | struct snd_ctl_elem_info *uinfo) | ||
47 | { | ||
48 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
49 | |||
50 | return snd_ctl_enum_info(uinfo, e->shift_l == e->shift_r ? 1 : 2, | ||
51 | e->items, e->texts); | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(snd_soc_info_enum_double); | ||
54 | |||
55 | /** | ||
56 | * snd_soc_get_enum_double - enumerated double mixer get callback | ||
57 | * @kcontrol: mixer control | ||
58 | * @ucontrol: control element information | ||
59 | * | ||
60 | * Callback to get the value of a double enumerated mixer. | ||
61 | * | ||
62 | * Returns 0 for success. | ||
63 | */ | ||
64 | int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, | ||
65 | struct snd_ctl_elem_value *ucontrol) | ||
66 | { | ||
67 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
68 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
69 | unsigned int val, item; | ||
70 | unsigned int reg_val; | ||
71 | int ret; | ||
72 | |||
73 | ret = snd_soc_component_read(component, e->reg, ®_val); | ||
74 | if (ret) | ||
75 | return ret; | ||
76 | val = (reg_val >> e->shift_l) & e->mask; | ||
77 | item = snd_soc_enum_val_to_item(e, val); | ||
78 | ucontrol->value.enumerated.item[0] = item; | ||
79 | if (e->shift_l != e->shift_r) { | ||
80 | val = (reg_val >> e->shift_l) & e->mask; | ||
81 | item = snd_soc_enum_val_to_item(e, val); | ||
82 | ucontrol->value.enumerated.item[1] = item; | ||
83 | } | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | EXPORT_SYMBOL_GPL(snd_soc_get_enum_double); | ||
88 | |||
89 | /** | ||
90 | * snd_soc_put_enum_double - enumerated double mixer put callback | ||
91 | * @kcontrol: mixer control | ||
92 | * @ucontrol: control element information | ||
93 | * | ||
94 | * Callback to set the value of a double enumerated mixer. | ||
95 | * | ||
96 | * Returns 0 for success. | ||
97 | */ | ||
98 | int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | ||
99 | struct snd_ctl_elem_value *ucontrol) | ||
100 | { | ||
101 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
102 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
103 | unsigned int *item = ucontrol->value.enumerated.item; | ||
104 | unsigned int val; | ||
105 | unsigned int mask; | ||
106 | |||
107 | if (item[0] >= e->items) | ||
108 | return -EINVAL; | ||
109 | val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; | ||
110 | mask = e->mask << e->shift_l; | ||
111 | if (e->shift_l != e->shift_r) { | ||
112 | if (item[1] >= e->items) | ||
113 | return -EINVAL; | ||
114 | val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; | ||
115 | mask |= e->mask << e->shift_r; | ||
116 | } | ||
117 | |||
118 | return snd_soc_component_update_bits(component, e->reg, mask, val); | ||
119 | } | ||
120 | EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); | ||
121 | |||
122 | /** | ||
123 | * snd_soc_read_signed - Read a codec register and interprete as signed value | ||
124 | * @component: component | ||
125 | * @reg: Register to read | ||
126 | * @mask: Mask to use after shifting the register value | ||
127 | * @shift: Right shift of register value | ||
128 | * @sign_bit: Bit that describes if a number is negative or not. | ||
129 | * @signed_val: Pointer to where the read value should be stored | ||
130 | * | ||
131 | * This functions reads a codec register. The register value is shifted right | ||
132 | * by 'shift' bits and masked with the given 'mask'. Afterwards it translates | ||
133 | * the given registervalue into a signed integer if sign_bit is non-zero. | ||
134 | * | ||
135 | * Returns 0 on sucess, otherwise an error value | ||
136 | */ | ||
137 | static int snd_soc_read_signed(struct snd_soc_component *component, | ||
138 | unsigned int reg, unsigned int mask, unsigned int shift, | ||
139 | unsigned int sign_bit, int *signed_val) | ||
140 | { | ||
141 | int ret; | ||
142 | unsigned int val; | ||
143 | |||
144 | ret = snd_soc_component_read(component, reg, &val); | ||
145 | if (ret < 0) | ||
146 | return ret; | ||
147 | |||
148 | val = (val >> shift) & mask; | ||
149 | |||
150 | if (!sign_bit) { | ||
151 | *signed_val = val; | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | /* non-negative number */ | ||
156 | if (!(val & BIT(sign_bit))) { | ||
157 | *signed_val = val; | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | ret = val; | ||
162 | |||
163 | /* | ||
164 | * The register most probably does not contain a full-sized int. | ||
165 | * Instead we have an arbitrary number of bits in a signed | ||
166 | * representation which has to be translated into a full-sized int. | ||
167 | * This is done by filling up all bits above the sign-bit. | ||
168 | */ | ||
169 | ret |= ~((int)(BIT(sign_bit) - 1)); | ||
170 | |||
171 | *signed_val = ret; | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * snd_soc_info_volsw - single mixer info callback | ||
178 | * @kcontrol: mixer control | ||
179 | * @uinfo: control element information | ||
180 | * | ||
181 | * Callback to provide information about a single mixer control, or a double | ||
182 | * mixer control that spans 2 registers. | ||
183 | * | ||
184 | * Returns 0 for success. | ||
185 | */ | ||
186 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | ||
187 | struct snd_ctl_elem_info *uinfo) | ||
188 | { | ||
189 | struct soc_mixer_control *mc = | ||
190 | (struct soc_mixer_control *)kcontrol->private_value; | ||
191 | int platform_max; | ||
192 | |||
193 | if (!mc->platform_max) | ||
194 | mc->platform_max = mc->max; | ||
195 | platform_max = mc->platform_max; | ||
196 | |||
197 | if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume")) | ||
198 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
199 | else | ||
200 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
201 | |||
202 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | ||
203 | uinfo->value.integer.min = 0; | ||
204 | uinfo->value.integer.max = platform_max - mc->min; | ||
205 | return 0; | ||
206 | } | ||
207 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | ||
208 | |||
209 | /** | ||
210 | * snd_soc_get_volsw - single mixer get callback | ||
211 | * @kcontrol: mixer control | ||
212 | * @ucontrol: control element information | ||
213 | * | ||
214 | * Callback to get the value of a single mixer control, or a double mixer | ||
215 | * control that spans 2 registers. | ||
216 | * | ||
217 | * Returns 0 for success. | ||
218 | */ | ||
219 | int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | ||
220 | struct snd_ctl_elem_value *ucontrol) | ||
221 | { | ||
222 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
223 | struct soc_mixer_control *mc = | ||
224 | (struct soc_mixer_control *)kcontrol->private_value; | ||
225 | unsigned int reg = mc->reg; | ||
226 | unsigned int reg2 = mc->rreg; | ||
227 | unsigned int shift = mc->shift; | ||
228 | unsigned int rshift = mc->rshift; | ||
229 | int max = mc->max; | ||
230 | int min = mc->min; | ||
231 | int sign_bit = mc->sign_bit; | ||
232 | unsigned int mask = (1 << fls(max)) - 1; | ||
233 | unsigned int invert = mc->invert; | ||
234 | int val; | ||
235 | int ret; | ||
236 | |||
237 | if (sign_bit) | ||
238 | mask = BIT(sign_bit + 1) - 1; | ||
239 | |||
240 | ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); | ||
241 | if (ret) | ||
242 | return ret; | ||
243 | |||
244 | ucontrol->value.integer.value[0] = val - min; | ||
245 | if (invert) | ||
246 | ucontrol->value.integer.value[0] = | ||
247 | max - ucontrol->value.integer.value[0]; | ||
248 | |||
249 | if (snd_soc_volsw_is_stereo(mc)) { | ||
250 | if (reg == reg2) | ||
251 | ret = snd_soc_read_signed(component, reg, mask, rshift, | ||
252 | sign_bit, &val); | ||
253 | else | ||
254 | ret = snd_soc_read_signed(component, reg2, mask, shift, | ||
255 | sign_bit, &val); | ||
256 | if (ret) | ||
257 | return ret; | ||
258 | |||
259 | ucontrol->value.integer.value[1] = val - min; | ||
260 | if (invert) | ||
261 | ucontrol->value.integer.value[1] = | ||
262 | max - ucontrol->value.integer.value[1]; | ||
263 | } | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw); | ||
268 | |||
269 | /** | ||
270 | * snd_soc_put_volsw - single mixer put callback | ||
271 | * @kcontrol: mixer control | ||
272 | * @ucontrol: control element information | ||
273 | * | ||
274 | * Callback to set the value of a single mixer control, or a double mixer | ||
275 | * control that spans 2 registers. | ||
276 | * | ||
277 | * Returns 0 for success. | ||
278 | */ | ||
279 | int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | ||
280 | struct snd_ctl_elem_value *ucontrol) | ||
281 | { | ||
282 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
283 | struct soc_mixer_control *mc = | ||
284 | (struct soc_mixer_control *)kcontrol->private_value; | ||
285 | unsigned int reg = mc->reg; | ||
286 | unsigned int reg2 = mc->rreg; | ||
287 | unsigned int shift = mc->shift; | ||
288 | unsigned int rshift = mc->rshift; | ||
289 | int max = mc->max; | ||
290 | int min = mc->min; | ||
291 | unsigned int sign_bit = mc->sign_bit; | ||
292 | unsigned int mask = (1 << fls(max)) - 1; | ||
293 | unsigned int invert = mc->invert; | ||
294 | int err; | ||
295 | bool type_2r = false; | ||
296 | unsigned int val2 = 0; | ||
297 | unsigned int val, val_mask; | ||
298 | |||
299 | if (sign_bit) | ||
300 | mask = BIT(sign_bit + 1) - 1; | ||
301 | |||
302 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
303 | if (invert) | ||
304 | val = max - val; | ||
305 | val_mask = mask << shift; | ||
306 | val = val << shift; | ||
307 | if (snd_soc_volsw_is_stereo(mc)) { | ||
308 | val2 = ((ucontrol->value.integer.value[1] + min) & mask); | ||
309 | if (invert) | ||
310 | val2 = max - val2; | ||
311 | if (reg == reg2) { | ||
312 | val_mask |= mask << rshift; | ||
313 | val |= val2 << rshift; | ||
314 | } else { | ||
315 | val2 = val2 << shift; | ||
316 | type_2r = true; | ||
317 | } | ||
318 | } | ||
319 | err = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
320 | if (err < 0) | ||
321 | return err; | ||
322 | |||
323 | if (type_2r) | ||
324 | err = snd_soc_component_update_bits(component, reg2, val_mask, | ||
325 | val2); | ||
326 | |||
327 | return err; | ||
328 | } | ||
329 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw); | ||
330 | |||
331 | /** | ||
332 | * snd_soc_get_volsw_sx - single mixer get callback | ||
333 | * @kcontrol: mixer control | ||
334 | * @ucontrol: control element information | ||
335 | * | ||
336 | * Callback to get the value of a single mixer control, or a double mixer | ||
337 | * control that spans 2 registers. | ||
338 | * | ||
339 | * Returns 0 for success. | ||
340 | */ | ||
341 | int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, | ||
342 | struct snd_ctl_elem_value *ucontrol) | ||
343 | { | ||
344 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
345 | struct soc_mixer_control *mc = | ||
346 | (struct soc_mixer_control *)kcontrol->private_value; | ||
347 | unsigned int reg = mc->reg; | ||
348 | unsigned int reg2 = mc->rreg; | ||
349 | unsigned int shift = mc->shift; | ||
350 | unsigned int rshift = mc->rshift; | ||
351 | int max = mc->max; | ||
352 | int min = mc->min; | ||
353 | int mask = (1 << (fls(min + max) - 1)) - 1; | ||
354 | unsigned int val; | ||
355 | int ret; | ||
356 | |||
357 | ret = snd_soc_component_read(component, reg, &val); | ||
358 | if (ret < 0) | ||
359 | return ret; | ||
360 | |||
361 | ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; | ||
362 | |||
363 | if (snd_soc_volsw_is_stereo(mc)) { | ||
364 | ret = snd_soc_component_read(component, reg2, &val); | ||
365 | if (ret < 0) | ||
366 | return ret; | ||
367 | |||
368 | val = ((val >> rshift) - min) & mask; | ||
369 | ucontrol->value.integer.value[1] = val; | ||
370 | } | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx); | ||
375 | |||
376 | /** | ||
377 | * snd_soc_put_volsw_sx - double mixer set callback | ||
378 | * @kcontrol: mixer control | ||
379 | * @uinfo: control element information | ||
380 | * | ||
381 | * Callback to set the value of a double mixer control that spans 2 registers. | ||
382 | * | ||
383 | * Returns 0 for success. | ||
384 | */ | ||
385 | int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, | ||
386 | struct snd_ctl_elem_value *ucontrol) | ||
387 | { | ||
388 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
389 | struct soc_mixer_control *mc = | ||
390 | (struct soc_mixer_control *)kcontrol->private_value; | ||
391 | |||
392 | unsigned int reg = mc->reg; | ||
393 | unsigned int reg2 = mc->rreg; | ||
394 | unsigned int shift = mc->shift; | ||
395 | unsigned int rshift = mc->rshift; | ||
396 | int max = mc->max; | ||
397 | int min = mc->min; | ||
398 | int mask = (1 << (fls(min + max) - 1)) - 1; | ||
399 | int err = 0; | ||
400 | unsigned int val, val_mask, val2 = 0; | ||
401 | |||
402 | val_mask = mask << shift; | ||
403 | val = (ucontrol->value.integer.value[0] + min) & mask; | ||
404 | val = val << shift; | ||
405 | |||
406 | err = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
407 | if (err < 0) | ||
408 | return err; | ||
409 | |||
410 | if (snd_soc_volsw_is_stereo(mc)) { | ||
411 | val_mask = mask << rshift; | ||
412 | val2 = (ucontrol->value.integer.value[1] + min) & mask; | ||
413 | val2 = val2 << rshift; | ||
414 | |||
415 | err = snd_soc_component_update_bits(component, reg2, val_mask, | ||
416 | val2); | ||
417 | } | ||
418 | return err; | ||
419 | } | ||
420 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); | ||
421 | |||
422 | /** | ||
423 | * snd_soc_info_volsw_range - single mixer info callback with range. | ||
424 | * @kcontrol: mixer control | ||
425 | * @uinfo: control element information | ||
426 | * | ||
427 | * Callback to provide information, within a range, about a single | ||
428 | * mixer control. | ||
429 | * | ||
430 | * returns 0 for success. | ||
431 | */ | ||
432 | int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, | ||
433 | struct snd_ctl_elem_info *uinfo) | ||
434 | { | ||
435 | struct soc_mixer_control *mc = | ||
436 | (struct soc_mixer_control *)kcontrol->private_value; | ||
437 | int platform_max; | ||
438 | int min = mc->min; | ||
439 | |||
440 | if (!mc->platform_max) | ||
441 | mc->platform_max = mc->max; | ||
442 | platform_max = mc->platform_max; | ||
443 | |||
444 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
445 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | ||
446 | uinfo->value.integer.min = 0; | ||
447 | uinfo->value.integer.max = platform_max - min; | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); | ||
452 | |||
453 | /** | ||
454 | * snd_soc_put_volsw_range - single mixer put value callback with range. | ||
455 | * @kcontrol: mixer control | ||
456 | * @ucontrol: control element information | ||
457 | * | ||
458 | * Callback to set the value, within a range, for a single mixer control. | ||
459 | * | ||
460 | * Returns 0 for success. | ||
461 | */ | ||
462 | int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | ||
463 | struct snd_ctl_elem_value *ucontrol) | ||
464 | { | ||
465 | struct soc_mixer_control *mc = | ||
466 | (struct soc_mixer_control *)kcontrol->private_value; | ||
467 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
468 | unsigned int reg = mc->reg; | ||
469 | unsigned int rreg = mc->rreg; | ||
470 | unsigned int shift = mc->shift; | ||
471 | int min = mc->min; | ||
472 | int max = mc->max; | ||
473 | unsigned int mask = (1 << fls(max)) - 1; | ||
474 | unsigned int invert = mc->invert; | ||
475 | unsigned int val, val_mask; | ||
476 | int ret; | ||
477 | |||
478 | if (invert) | ||
479 | val = (max - ucontrol->value.integer.value[0]) & mask; | ||
480 | else | ||
481 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
482 | val_mask = mask << shift; | ||
483 | val = val << shift; | ||
484 | |||
485 | ret = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
486 | if (ret < 0) | ||
487 | return ret; | ||
488 | |||
489 | if (snd_soc_volsw_is_stereo(mc)) { | ||
490 | if (invert) | ||
491 | val = (max - ucontrol->value.integer.value[1]) & mask; | ||
492 | else | ||
493 | val = ((ucontrol->value.integer.value[1] + min) & mask); | ||
494 | val_mask = mask << shift; | ||
495 | val = val << shift; | ||
496 | |||
497 | ret = snd_soc_component_update_bits(component, rreg, val_mask, | ||
498 | val); | ||
499 | } | ||
500 | |||
501 | return ret; | ||
502 | } | ||
503 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); | ||
504 | |||
505 | /** | ||
506 | * snd_soc_get_volsw_range - single mixer get callback with range | ||
507 | * @kcontrol: mixer control | ||
508 | * @ucontrol: control element information | ||
509 | * | ||
510 | * Callback to get the value, within a range, of a single mixer control. | ||
511 | * | ||
512 | * Returns 0 for success. | ||
513 | */ | ||
514 | int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | ||
515 | struct snd_ctl_elem_value *ucontrol) | ||
516 | { | ||
517 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
518 | struct soc_mixer_control *mc = | ||
519 | (struct soc_mixer_control *)kcontrol->private_value; | ||
520 | unsigned int reg = mc->reg; | ||
521 | unsigned int rreg = mc->rreg; | ||
522 | unsigned int shift = mc->shift; | ||
523 | int min = mc->min; | ||
524 | int max = mc->max; | ||
525 | unsigned int mask = (1 << fls(max)) - 1; | ||
526 | unsigned int invert = mc->invert; | ||
527 | unsigned int val; | ||
528 | int ret; | ||
529 | |||
530 | ret = snd_soc_component_read(component, reg, &val); | ||
531 | if (ret) | ||
532 | return ret; | ||
533 | |||
534 | ucontrol->value.integer.value[0] = (val >> shift) & mask; | ||
535 | if (invert) | ||
536 | ucontrol->value.integer.value[0] = | ||
537 | max - ucontrol->value.integer.value[0]; | ||
538 | else | ||
539 | ucontrol->value.integer.value[0] = | ||
540 | ucontrol->value.integer.value[0] - min; | ||
541 | |||
542 | if (snd_soc_volsw_is_stereo(mc)) { | ||
543 | ret = snd_soc_component_read(component, rreg, &val); | ||
544 | if (ret) | ||
545 | return ret; | ||
546 | |||
547 | ucontrol->value.integer.value[1] = (val >> shift) & mask; | ||
548 | if (invert) | ||
549 | ucontrol->value.integer.value[1] = | ||
550 | max - ucontrol->value.integer.value[1]; | ||
551 | else | ||
552 | ucontrol->value.integer.value[1] = | ||
553 | ucontrol->value.integer.value[1] - min; | ||
554 | } | ||
555 | |||
556 | return 0; | ||
557 | } | ||
558 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); | ||
559 | |||
560 | /** | ||
561 | * snd_soc_limit_volume - Set new limit to an existing volume control. | ||
562 | * | ||
563 | * @codec: where to look for the control | ||
564 | * @name: Name of the control | ||
565 | * @max: new maximum limit | ||
566 | * | ||
567 | * Return 0 for success, else error. | ||
568 | */ | ||
569 | int snd_soc_limit_volume(struct snd_soc_codec *codec, | ||
570 | const char *name, int max) | ||
571 | { | ||
572 | struct snd_card *card = codec->component.card->snd_card; | ||
573 | struct snd_kcontrol *kctl; | ||
574 | struct soc_mixer_control *mc; | ||
575 | int found = 0; | ||
576 | int ret = -EINVAL; | ||
577 | |||
578 | /* Sanity check for name and max */ | ||
579 | if (unlikely(!name || max <= 0)) | ||
580 | return -EINVAL; | ||
581 | |||
582 | list_for_each_entry(kctl, &card->controls, list) { | ||
583 | if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) { | ||
584 | found = 1; | ||
585 | break; | ||
586 | } | ||
587 | } | ||
588 | if (found) { | ||
589 | mc = (struct soc_mixer_control *)kctl->private_value; | ||
590 | if (max <= mc->max) { | ||
591 | mc->platform_max = max; | ||
592 | ret = 0; | ||
593 | } | ||
594 | } | ||
595 | return ret; | ||
596 | } | ||
597 | EXPORT_SYMBOL_GPL(snd_soc_limit_volume); | ||
598 | |||
599 | int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, | ||
600 | struct snd_ctl_elem_info *uinfo) | ||
601 | { | ||
602 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
603 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
604 | |||
605 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
606 | uinfo->count = params->num_regs * component->val_bytes; | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info); | ||
611 | |||
612 | int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, | ||
613 | struct snd_ctl_elem_value *ucontrol) | ||
614 | { | ||
615 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
616 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
617 | int ret; | ||
618 | |||
619 | if (component->regmap) | ||
620 | ret = regmap_raw_read(component->regmap, params->base, | ||
621 | ucontrol->value.bytes.data, | ||
622 | params->num_regs * component->val_bytes); | ||
623 | else | ||
624 | ret = -EINVAL; | ||
625 | |||
626 | /* Hide any masked bytes to ensure consistent data reporting */ | ||
627 | if (ret == 0 && params->mask) { | ||
628 | switch (component->val_bytes) { | ||
629 | case 1: | ||
630 | ucontrol->value.bytes.data[0] &= ~params->mask; | ||
631 | break; | ||
632 | case 2: | ||
633 | ((u16 *)(&ucontrol->value.bytes.data))[0] | ||
634 | &= cpu_to_be16(~params->mask); | ||
635 | break; | ||
636 | case 4: | ||
637 | ((u32 *)(&ucontrol->value.bytes.data))[0] | ||
638 | &= cpu_to_be32(~params->mask); | ||
639 | break; | ||
640 | default: | ||
641 | return -EINVAL; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | return ret; | ||
646 | } | ||
647 | EXPORT_SYMBOL_GPL(snd_soc_bytes_get); | ||
648 | |||
649 | int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, | ||
650 | struct snd_ctl_elem_value *ucontrol) | ||
651 | { | ||
652 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
653 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
654 | int ret, len; | ||
655 | unsigned int val, mask; | ||
656 | void *data; | ||
657 | |||
658 | if (!component->regmap || !params->num_regs) | ||
659 | return -EINVAL; | ||
660 | |||
661 | len = params->num_regs * component->val_bytes; | ||
662 | |||
663 | data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); | ||
664 | if (!data) | ||
665 | return -ENOMEM; | ||
666 | |||
667 | /* | ||
668 | * If we've got a mask then we need to preserve the register | ||
669 | * bits. We shouldn't modify the incoming data so take a | ||
670 | * copy. | ||
671 | */ | ||
672 | if (params->mask) { | ||
673 | ret = regmap_read(component->regmap, params->base, &val); | ||
674 | if (ret != 0) | ||
675 | goto out; | ||
676 | |||
677 | val &= params->mask; | ||
678 | |||
679 | switch (component->val_bytes) { | ||
680 | case 1: | ||
681 | ((u8 *)data)[0] &= ~params->mask; | ||
682 | ((u8 *)data)[0] |= val; | ||
683 | break; | ||
684 | case 2: | ||
685 | mask = ~params->mask; | ||
686 | ret = regmap_parse_val(component->regmap, | ||
687 | &mask, &mask); | ||
688 | if (ret != 0) | ||
689 | goto out; | ||
690 | |||
691 | ((u16 *)data)[0] &= mask; | ||
692 | |||
693 | ret = regmap_parse_val(component->regmap, | ||
694 | &val, &val); | ||
695 | if (ret != 0) | ||
696 | goto out; | ||
697 | |||
698 | ((u16 *)data)[0] |= val; | ||
699 | break; | ||
700 | case 4: | ||
701 | mask = ~params->mask; | ||
702 | ret = regmap_parse_val(component->regmap, | ||
703 | &mask, &mask); | ||
704 | if (ret != 0) | ||
705 | goto out; | ||
706 | |||
707 | ((u32 *)data)[0] &= mask; | ||
708 | |||
709 | ret = regmap_parse_val(component->regmap, | ||
710 | &val, &val); | ||
711 | if (ret != 0) | ||
712 | goto out; | ||
713 | |||
714 | ((u32 *)data)[0] |= val; | ||
715 | break; | ||
716 | default: | ||
717 | ret = -EINVAL; | ||
718 | goto out; | ||
719 | } | ||
720 | } | ||
721 | |||
722 | ret = regmap_raw_write(component->regmap, params->base, | ||
723 | data, len); | ||
724 | |||
725 | out: | ||
726 | kfree(data); | ||
727 | |||
728 | return ret; | ||
729 | } | ||
730 | EXPORT_SYMBOL_GPL(snd_soc_bytes_put); | ||
731 | |||
732 | int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, | ||
733 | struct snd_ctl_elem_info *ucontrol) | ||
734 | { | ||
735 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
736 | |||
737 | ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
738 | ucontrol->count = params->max; | ||
739 | |||
740 | return 0; | ||
741 | } | ||
742 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); | ||
743 | |||
744 | int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, | ||
745 | unsigned int size, unsigned int __user *tlv) | ||
746 | { | ||
747 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
748 | unsigned int count = size < params->max ? size : params->max; | ||
749 | int ret = -ENXIO; | ||
750 | |||
751 | switch (op_flag) { | ||
752 | case SNDRV_CTL_TLV_OP_READ: | ||
753 | if (params->get) | ||
754 | ret = params->get(tlv, count); | ||
755 | break; | ||
756 | case SNDRV_CTL_TLV_OP_WRITE: | ||
757 | if (params->put) | ||
758 | ret = params->put(tlv, count); | ||
759 | break; | ||
760 | } | ||
761 | return ret; | ||
762 | } | ||
763 | EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); | ||
764 | |||
765 | /** | ||
766 | * snd_soc_info_xr_sx - signed multi register info callback | ||
767 | * @kcontrol: mreg control | ||
768 | * @uinfo: control element information | ||
769 | * | ||
770 | * Callback to provide information of a control that can | ||
771 | * span multiple codec registers which together | ||
772 | * forms a single signed value in a MSB/LSB manner. | ||
773 | * | ||
774 | * Returns 0 for success. | ||
775 | */ | ||
776 | int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, | ||
777 | struct snd_ctl_elem_info *uinfo) | ||
778 | { | ||
779 | struct soc_mreg_control *mc = | ||
780 | (struct soc_mreg_control *)kcontrol->private_value; | ||
781 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
782 | uinfo->count = 1; | ||
783 | uinfo->value.integer.min = mc->min; | ||
784 | uinfo->value.integer.max = mc->max; | ||
785 | |||
786 | return 0; | ||
787 | } | ||
788 | EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx); | ||
789 | |||
790 | /** | ||
791 | * snd_soc_get_xr_sx - signed multi register get callback | ||
792 | * @kcontrol: mreg control | ||
793 | * @ucontrol: control element information | ||
794 | * | ||
795 | * Callback to get the value of a control that can span | ||
796 | * multiple codec registers which together forms a single | ||
797 | * signed value in a MSB/LSB manner. The control supports | ||
798 | * specifying total no of bits used to allow for bitfields | ||
799 | * across the multiple codec registers. | ||
800 | * | ||
801 | * Returns 0 for success. | ||
802 | */ | ||
803 | int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, | ||
804 | struct snd_ctl_elem_value *ucontrol) | ||
805 | { | ||
806 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
807 | struct soc_mreg_control *mc = | ||
808 | (struct soc_mreg_control *)kcontrol->private_value; | ||
809 | unsigned int regbase = mc->regbase; | ||
810 | unsigned int regcount = mc->regcount; | ||
811 | unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; | ||
812 | unsigned int regwmask = (1<<regwshift)-1; | ||
813 | unsigned int invert = mc->invert; | ||
814 | unsigned long mask = (1UL<<mc->nbits)-1; | ||
815 | long min = mc->min; | ||
816 | long max = mc->max; | ||
817 | long val = 0; | ||
818 | unsigned int regval; | ||
819 | unsigned int i; | ||
820 | int ret; | ||
821 | |||
822 | for (i = 0; i < regcount; i++) { | ||
823 | ret = snd_soc_component_read(component, regbase+i, ®val); | ||
824 | if (ret) | ||
825 | return ret; | ||
826 | val |= (regval & regwmask) << (regwshift*(regcount-i-1)); | ||
827 | } | ||
828 | val &= mask; | ||
829 | if (min < 0 && val > max) | ||
830 | val |= ~mask; | ||
831 | if (invert) | ||
832 | val = max - val; | ||
833 | ucontrol->value.integer.value[0] = val; | ||
834 | |||
835 | return 0; | ||
836 | } | ||
837 | EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx); | ||
838 | |||
839 | /** | ||
840 | * snd_soc_put_xr_sx - signed multi register get callback | ||
841 | * @kcontrol: mreg control | ||
842 | * @ucontrol: control element information | ||
843 | * | ||
844 | * Callback to set the value of a control that can span | ||
845 | * multiple codec registers which together forms a single | ||
846 | * signed value in a MSB/LSB manner. The control supports | ||
847 | * specifying total no of bits used to allow for bitfields | ||
848 | * across the multiple codec registers. | ||
849 | * | ||
850 | * Returns 0 for success. | ||
851 | */ | ||
852 | int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, | ||
853 | struct snd_ctl_elem_value *ucontrol) | ||
854 | { | ||
855 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
856 | struct soc_mreg_control *mc = | ||
857 | (struct soc_mreg_control *)kcontrol->private_value; | ||
858 | unsigned int regbase = mc->regbase; | ||
859 | unsigned int regcount = mc->regcount; | ||
860 | unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; | ||
861 | unsigned int regwmask = (1<<regwshift)-1; | ||
862 | unsigned int invert = mc->invert; | ||
863 | unsigned long mask = (1UL<<mc->nbits)-1; | ||
864 | long max = mc->max; | ||
865 | long val = ucontrol->value.integer.value[0]; | ||
866 | unsigned int i, regval, regmask; | ||
867 | int err; | ||
868 | |||
869 | if (invert) | ||
870 | val = max - val; | ||
871 | val &= mask; | ||
872 | for (i = 0; i < regcount; i++) { | ||
873 | regval = (val >> (regwshift*(regcount-i-1))) & regwmask; | ||
874 | regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; | ||
875 | err = snd_soc_component_update_bits(component, regbase+i, | ||
876 | regmask, regval); | ||
877 | if (err < 0) | ||
878 | return err; | ||
879 | } | ||
880 | |||
881 | return 0; | ||
882 | } | ||
883 | EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx); | ||
884 | |||
885 | /** | ||
886 | * snd_soc_get_strobe - strobe get callback | ||
887 | * @kcontrol: mixer control | ||
888 | * @ucontrol: control element information | ||
889 | * | ||
890 | * Callback get the value of a strobe mixer control. | ||
891 | * | ||
892 | * Returns 0 for success. | ||
893 | */ | ||
894 | int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, | ||
895 | struct snd_ctl_elem_value *ucontrol) | ||
896 | { | ||
897 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
898 | struct soc_mixer_control *mc = | ||
899 | (struct soc_mixer_control *)kcontrol->private_value; | ||
900 | unsigned int reg = mc->reg; | ||
901 | unsigned int shift = mc->shift; | ||
902 | unsigned int mask = 1 << shift; | ||
903 | unsigned int invert = mc->invert != 0; | ||
904 | unsigned int val; | ||
905 | int ret; | ||
906 | |||
907 | ret = snd_soc_component_read(component, reg, &val); | ||
908 | if (ret) | ||
909 | return ret; | ||
910 | |||
911 | val &= mask; | ||
912 | |||
913 | if (shift != 0 && val != 0) | ||
914 | val = val >> shift; | ||
915 | ucontrol->value.enumerated.item[0] = val ^ invert; | ||
916 | |||
917 | return 0; | ||
918 | } | ||
919 | EXPORT_SYMBOL_GPL(snd_soc_get_strobe); | ||
920 | |||
921 | /** | ||
922 | * snd_soc_put_strobe - strobe put callback | ||
923 | * @kcontrol: mixer control | ||
924 | * @ucontrol: control element information | ||
925 | * | ||
926 | * Callback strobe a register bit to high then low (or the inverse) | ||
927 | * in one pass of a single mixer enum control. | ||
928 | * | ||
929 | * Returns 1 for success. | ||
930 | */ | ||
931 | int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, | ||
932 | struct snd_ctl_elem_value *ucontrol) | ||
933 | { | ||
934 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
935 | struct soc_mixer_control *mc = | ||
936 | (struct soc_mixer_control *)kcontrol->private_value; | ||
937 | unsigned int reg = mc->reg; | ||
938 | unsigned int shift = mc->shift; | ||
939 | unsigned int mask = 1 << shift; | ||
940 | unsigned int invert = mc->invert != 0; | ||
941 | unsigned int strobe = ucontrol->value.enumerated.item[0] != 0; | ||
942 | unsigned int val1 = (strobe ^ invert) ? mask : 0; | ||
943 | unsigned int val2 = (strobe ^ invert) ? 0 : mask; | ||
944 | int err; | ||
945 | |||
946 | err = snd_soc_component_update_bits(component, reg, mask, val1); | ||
947 | if (err < 0) | ||
948 | return err; | ||
949 | |||
950 | return snd_soc_component_update_bits(component, reg, mask, val2); | ||
951 | } | ||
952 | EXPORT_SYMBOL_GPL(snd_soc_put_strobe); | ||
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 70e8088a5468..5de2440ff25c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -654,6 +654,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
654 | codec_dai->rate = 0; | 654 | codec_dai->rate = 0; |
655 | } | 655 | } |
656 | 656 | ||
657 | snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); | ||
658 | |||
657 | if (cpu_dai->driver->ops->shutdown) | 659 | if (cpu_dai->driver->ops->shutdown) |
658 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | 660 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
659 | 661 | ||
@@ -772,6 +774,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
772 | for (i = 0; i < rtd->num_codecs; i++) | 774 | for (i = 0; i < rtd->num_codecs; i++) |
773 | snd_soc_dai_digital_mute(rtd->codec_dais[i], 0, | 775 | snd_soc_dai_digital_mute(rtd->codec_dais[i], 0, |
774 | substream->stream); | 776 | substream->stream); |
777 | snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); | ||
775 | 778 | ||
776 | out: | 779 | out: |
777 | mutex_unlock(&rtd->pcm_mutex); | 780 | mutex_unlock(&rtd->pcm_mutex); |
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index cd71fd889d8b..00b7e2d02690 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c | |||
@@ -292,7 +292,7 @@ static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
292 | struct snd_card *card = rtd->card->snd_card; | 292 | struct snd_card *card = rtd->card->snd_card; |
293 | struct snd_soc_dai *dai = rtd->cpu_dai; | 293 | struct snd_soc_dai *dai = rtd->cpu_dai; |
294 | struct snd_pcm *pcm = rtd->pcm; | 294 | struct snd_pcm *pcm = rtd->pcm; |
295 | struct platform_device *pdev = to_platform_device(dai->platform->dev); | 295 | struct platform_device *pdev = to_platform_device(rtd->platform->dev); |
296 | struct txx9aclc_soc_device *dev; | 296 | struct txx9aclc_soc_device *dev; |
297 | struct resource *r; | 297 | struct resource *r; |
298 | int i; | 298 | int i; |