aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r--sound/soc/soc-core.c255
1 files changed, 209 insertions, 46 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index ad7f9528d751..998569d60330 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -316,7 +316,7 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
316 316
317 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates || 317 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates ||
318 machine->symmetric_rates) { 318 machine->symmetric_rates) {
319 dev_dbg(card->dev, "Symmetry forces %dHz rate\n", 319 dev_dbg(card->dev, "Symmetry forces %dHz rate\n",
320 machine->rate); 320 machine->rate);
321 321
322 ret = snd_pcm_hw_constraint_minmax(substream->runtime, 322 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
@@ -405,6 +405,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
405 codec_dai->playback.formats & cpu_dai->playback.formats; 405 codec_dai->playback.formats & cpu_dai->playback.formats;
406 runtime->hw.rates = 406 runtime->hw.rates =
407 codec_dai->playback.rates & cpu_dai->playback.rates; 407 codec_dai->playback.rates & cpu_dai->playback.rates;
408 if (codec_dai->playback.rates
409 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
410 runtime->hw.rates |= cpu_dai->playback.rates;
411 if (cpu_dai->playback.rates
412 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
413 runtime->hw.rates |= codec_dai->playback.rates;
408 } else { 414 } else {
409 runtime->hw.rate_min = 415 runtime->hw.rate_min =
410 max(codec_dai->capture.rate_min, 416 max(codec_dai->capture.rate_min,
@@ -422,6 +428,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
422 codec_dai->capture.formats & cpu_dai->capture.formats; 428 codec_dai->capture.formats & cpu_dai->capture.formats;
423 runtime->hw.rates = 429 runtime->hw.rates =
424 codec_dai->capture.rates & cpu_dai->capture.rates; 430 codec_dai->capture.rates & cpu_dai->capture.rates;
431 if (codec_dai->capture.rates
432 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
433 runtime->hw.rates |= cpu_dai->capture.rates;
434 if (cpu_dai->capture.rates
435 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
436 runtime->hw.rates |= codec_dai->capture.rates;
425 } 437 }
426 438
427 snd_pcm_limit_hw_rates(runtime); 439 snd_pcm_limit_hw_rates(runtime);
@@ -455,12 +467,15 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
455 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, 467 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
456 runtime->hw.rate_max); 468 runtime->hw.rate_max);
457 469
458 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 470 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
459 cpu_dai->playback.active = codec_dai->playback.active = 1; 471 cpu_dai->playback.active++;
460 else 472 codec_dai->playback.active++;
461 cpu_dai->capture.active = codec_dai->capture.active = 1; 473 } else {
462 cpu_dai->active = codec_dai->active = 1; 474 cpu_dai->capture.active++;
463 cpu_dai->runtime = runtime; 475 codec_dai->capture.active++;
476 }
477 cpu_dai->active++;
478 codec_dai->active++;
464 card->codec->active++; 479 card->codec->active++;
465 mutex_unlock(&pcm_mutex); 480 mutex_unlock(&pcm_mutex);
466 return 0; 481 return 0;
@@ -536,15 +551,16 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
536 551
537 mutex_lock(&pcm_mutex); 552 mutex_lock(&pcm_mutex);
538 553
539 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 554 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
540 cpu_dai->playback.active = codec_dai->playback.active = 0; 555 cpu_dai->playback.active--;
541 else 556 codec_dai->playback.active--;
542 cpu_dai->capture.active = codec_dai->capture.active = 0; 557 } else {
543 558 cpu_dai->capture.active--;
544 if (codec_dai->playback.active == 0 && 559 codec_dai->capture.active--;
545 codec_dai->capture.active == 0) {
546 cpu_dai->active = codec_dai->active = 0;
547 } 560 }
561
562 cpu_dai->active--;
563 codec_dai->active--;
548 codec->active--; 564 codec->active--;
549 565
550 /* Muting the DAC suppresses artifacts caused during digital 566 /* Muting the DAC suppresses artifacts caused during digital
@@ -564,7 +580,6 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
564 580
565 if (platform->pcm_ops->close) 581 if (platform->pcm_ops->close)
566 platform->pcm_ops->close(substream); 582 platform->pcm_ops->close(substream);
567 cpu_dai->runtime = NULL;
568 583
569 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 584 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
570 /* start delayed pop wq here for playback streams */ 585 /* start delayed pop wq here for playback streams */
@@ -802,6 +817,41 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
802 return 0; 817 return 0;
803} 818}
804 819
820/*
821 * soc level wrapper for pointer callback
822 * If cpu_dai, codec_dai, platform driver has the delay callback, than
823 * the runtime->delay will be updated accordingly.
824 */
825static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
826{
827 struct snd_soc_pcm_runtime *rtd = substream->private_data;
828 struct snd_soc_device *socdev = rtd->socdev;
829 struct snd_soc_card *card = socdev->card;
830 struct snd_soc_platform *platform = card->platform;
831 struct snd_soc_dai_link *machine = rtd->dai;
832 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
833 struct snd_soc_dai *codec_dai = machine->codec_dai;
834 struct snd_pcm_runtime *runtime = substream->runtime;
835 snd_pcm_uframes_t offset = 0;
836 snd_pcm_sframes_t delay = 0;
837
838 if (platform->pcm_ops->pointer)
839 offset = platform->pcm_ops->pointer(substream);
840
841 if (cpu_dai->ops->delay)
842 delay += cpu_dai->ops->delay(substream, cpu_dai);
843
844 if (codec_dai->ops->delay)
845 delay += codec_dai->ops->delay(substream, codec_dai);
846
847 if (platform->delay)
848 delay += platform->delay(substream, codec_dai);
849
850 runtime->delay = delay;
851
852 return offset;
853}
854
805/* ASoC PCM operations */ 855/* ASoC PCM operations */
806static struct snd_pcm_ops soc_pcm_ops = { 856static struct snd_pcm_ops soc_pcm_ops = {
807 .open = soc_pcm_open, 857 .open = soc_pcm_open,
@@ -810,6 +860,7 @@ static struct snd_pcm_ops soc_pcm_ops = {
810 .hw_free = soc_pcm_hw_free, 860 .hw_free = soc_pcm_hw_free,
811 .prepare = soc_pcm_prepare, 861 .prepare = soc_pcm_prepare,
812 .trigger = soc_pcm_trigger, 862 .trigger = soc_pcm_trigger,
863 .pointer = soc_pcm_pointer,
813}; 864};
814 865
815#ifdef CONFIG_PM 866#ifdef CONFIG_PM
@@ -843,23 +894,35 @@ static int soc_suspend(struct device *dev)
843 /* mute any active DAC's */ 894 /* mute any active DAC's */
844 for (i = 0; i < card->num_links; i++) { 895 for (i = 0; i < card->num_links; i++) {
845 struct snd_soc_dai *dai = card->dai_link[i].codec_dai; 896 struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
897
898 if (card->dai_link[i].ignore_suspend)
899 continue;
900
846 if (dai->ops->digital_mute && dai->playback.active) 901 if (dai->ops->digital_mute && dai->playback.active)
847 dai->ops->digital_mute(dai, 1); 902 dai->ops->digital_mute(dai, 1);
848 } 903 }
849 904
850 /* suspend all pcms */ 905 /* suspend all pcms */
851 for (i = 0; i < card->num_links; i++) 906 for (i = 0; i < card->num_links; i++) {
907 if (card->dai_link[i].ignore_suspend)
908 continue;
909
852 snd_pcm_suspend_all(card->dai_link[i].pcm); 910 snd_pcm_suspend_all(card->dai_link[i].pcm);
911 }
853 912
854 if (card->suspend_pre) 913 if (card->suspend_pre)
855 card->suspend_pre(pdev, PMSG_SUSPEND); 914 card->suspend_pre(pdev, PMSG_SUSPEND);
856 915
857 for (i = 0; i < card->num_links; i++) { 916 for (i = 0; i < card->num_links; i++) {
858 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 917 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
918
919 if (card->dai_link[i].ignore_suspend)
920 continue;
921
859 if (cpu_dai->suspend && !cpu_dai->ac97_control) 922 if (cpu_dai->suspend && !cpu_dai->ac97_control)
860 cpu_dai->suspend(cpu_dai); 923 cpu_dai->suspend(cpu_dai);
861 if (platform->suspend) 924 if (platform->suspend)
862 platform->suspend(cpu_dai); 925 platform->suspend(&card->dai_link[i]);
863 } 926 }
864 927
865 /* close any waiting streams and save state */ 928 /* close any waiting streams and save state */
@@ -868,6 +931,10 @@ static int soc_suspend(struct device *dev)
868 931
869 for (i = 0; i < codec->num_dai; i++) { 932 for (i = 0; i < codec->num_dai; i++) {
870 char *stream = codec->dai[i].playback.stream_name; 933 char *stream = codec->dai[i].playback.stream_name;
934
935 if (card->dai_link[i].ignore_suspend)
936 continue;
937
871 if (stream != NULL) 938 if (stream != NULL)
872 snd_soc_dapm_stream_event(codec, stream, 939 snd_soc_dapm_stream_event(codec, stream,
873 SND_SOC_DAPM_STREAM_SUSPEND); 940 SND_SOC_DAPM_STREAM_SUSPEND);
@@ -877,11 +944,26 @@ static int soc_suspend(struct device *dev)
877 SND_SOC_DAPM_STREAM_SUSPEND); 944 SND_SOC_DAPM_STREAM_SUSPEND);
878 } 945 }
879 946
880 if (codec_dev->suspend) 947 /* If there are paths active then the CODEC will be held with
881 codec_dev->suspend(pdev, PMSG_SUSPEND); 948 * bias _ON and should not be suspended. */
949 if (codec_dev->suspend) {
950 switch (codec->bias_level) {
951 case SND_SOC_BIAS_STANDBY:
952 case SND_SOC_BIAS_OFF:
953 codec_dev->suspend(pdev, PMSG_SUSPEND);
954 break;
955 default:
956 dev_dbg(socdev->dev, "CODEC is on over suspend\n");
957 break;
958 }
959 }
882 960
883 for (i = 0; i < card->num_links; i++) { 961 for (i = 0; i < card->num_links; i++) {
884 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 962 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
963
964 if (card->dai_link[i].ignore_suspend)
965 continue;
966
885 if (cpu_dai->suspend && cpu_dai->ac97_control) 967 if (cpu_dai->suspend && cpu_dai->ac97_control)
886 cpu_dai->suspend(cpu_dai); 968 cpu_dai->suspend(cpu_dai);
887 } 969 }
@@ -913,20 +995,44 @@ static void soc_resume_deferred(struct work_struct *work)
913 995
914 dev_dbg(socdev->dev, "starting resume work\n"); 996 dev_dbg(socdev->dev, "starting resume work\n");
915 997
998 /* Bring us up into D2 so that DAPM starts enabling things */
999 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D2);
1000
916 if (card->resume_pre) 1001 if (card->resume_pre)
917 card->resume_pre(pdev); 1002 card->resume_pre(pdev);
918 1003
919 for (i = 0; i < card->num_links; i++) { 1004 for (i = 0; i < card->num_links; i++) {
920 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1005 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
1006
1007 if (card->dai_link[i].ignore_suspend)
1008 continue;
1009
921 if (cpu_dai->resume && cpu_dai->ac97_control) 1010 if (cpu_dai->resume && cpu_dai->ac97_control)
922 cpu_dai->resume(cpu_dai); 1011 cpu_dai->resume(cpu_dai);
923 } 1012 }
924 1013
925 if (codec_dev->resume) 1014 /* If the CODEC was idle over suspend then it will have been
926 codec_dev->resume(pdev); 1015 * left with bias OFF or STANDBY and suspended so we must now
1016 * resume. Otherwise the suspend was suppressed.
1017 */
1018 if (codec_dev->resume) {
1019 switch (codec->bias_level) {
1020 case SND_SOC_BIAS_STANDBY:
1021 case SND_SOC_BIAS_OFF:
1022 codec_dev->resume(pdev);
1023 break;
1024 default:
1025 dev_dbg(socdev->dev, "CODEC was on over suspend\n");
1026 break;
1027 }
1028 }
927 1029
928 for (i = 0; i < codec->num_dai; i++) { 1030 for (i = 0; i < codec->num_dai; i++) {
929 char *stream = codec->dai[i].playback.stream_name; 1031 char *stream = codec->dai[i].playback.stream_name;
1032
1033 if (card->dai_link[i].ignore_suspend)
1034 continue;
1035
930 if (stream != NULL) 1036 if (stream != NULL)
931 snd_soc_dapm_stream_event(codec, stream, 1037 snd_soc_dapm_stream_event(codec, stream,
932 SND_SOC_DAPM_STREAM_RESUME); 1038 SND_SOC_DAPM_STREAM_RESUME);
@@ -939,16 +1045,24 @@ static void soc_resume_deferred(struct work_struct *work)
939 /* unmute any active DACs */ 1045 /* unmute any active DACs */
940 for (i = 0; i < card->num_links; i++) { 1046 for (i = 0; i < card->num_links; i++) {
941 struct snd_soc_dai *dai = card->dai_link[i].codec_dai; 1047 struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
1048
1049 if (card->dai_link[i].ignore_suspend)
1050 continue;
1051
942 if (dai->ops->digital_mute && dai->playback.active) 1052 if (dai->ops->digital_mute && dai->playback.active)
943 dai->ops->digital_mute(dai, 0); 1053 dai->ops->digital_mute(dai, 0);
944 } 1054 }
945 1055
946 for (i = 0; i < card->num_links; i++) { 1056 for (i = 0; i < card->num_links; i++) {
947 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1057 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
1058
1059 if (card->dai_link[i].ignore_suspend)
1060 continue;
1061
948 if (cpu_dai->resume && !cpu_dai->ac97_control) 1062 if (cpu_dai->resume && !cpu_dai->ac97_control)
949 cpu_dai->resume(cpu_dai); 1063 cpu_dai->resume(cpu_dai);
950 if (platform->resume) 1064 if (platform->resume)
951 platform->resume(cpu_dai); 1065 platform->resume(&card->dai_link[i]);
952 } 1066 }
953 1067
954 if (card->resume_post) 1068 if (card->resume_post)
@@ -1233,26 +1347,25 @@ static int soc_remove(struct platform_device *pdev)
1233 struct snd_soc_platform *platform = card->platform; 1347 struct snd_soc_platform *platform = card->platform;
1234 struct snd_soc_codec_device *codec_dev = socdev->codec_dev; 1348 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
1235 1349
1236 if (!card->instantiated) 1350 if (card->instantiated) {
1237 return 0; 1351 run_delayed_work(&card->delayed_work);
1238 1352
1239 run_delayed_work(&card->delayed_work); 1353 if (platform->remove)
1354 platform->remove(pdev);
1240 1355
1241 if (platform->remove) 1356 if (codec_dev->remove)
1242 platform->remove(pdev); 1357 codec_dev->remove(pdev);
1243 1358
1244 if (codec_dev->remove) 1359 for (i = 0; i < card->num_links; i++) {
1245 codec_dev->remove(pdev); 1360 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
1361 if (cpu_dai->remove)
1362 cpu_dai->remove(pdev, cpu_dai);
1363 }
1246 1364
1247 for (i = 0; i < card->num_links; i++) { 1365 if (card->remove)
1248 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1366 card->remove(pdev);
1249 if (cpu_dai->remove)
1250 cpu_dai->remove(pdev, cpu_dai);
1251 } 1367 }
1252 1368
1253 if (card->remove)
1254 card->remove(pdev);
1255
1256 snd_soc_unregister_card(card); 1369 snd_soc_unregister_card(card);
1257 1370
1258 return 0; 1371 return 0;
@@ -1336,7 +1449,6 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
1336 dai_link->pcm = pcm; 1449 dai_link->pcm = pcm;
1337 pcm->private_data = rtd; 1450 pcm->private_data = rtd;
1338 soc_pcm_ops.mmap = platform->pcm_ops->mmap; 1451 soc_pcm_ops.mmap = platform->pcm_ops->mmap;
1339 soc_pcm_ops.pointer = platform->pcm_ops->pointer;
1340 soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; 1452 soc_pcm_ops.ioctl = platform->pcm_ops->ioctl;
1341 soc_pcm_ops.copy = platform->pcm_ops->copy; 1453 soc_pcm_ops.copy = platform->pcm_ops->copy;
1342 soc_pcm_ops.silence = platform->pcm_ops->silence; 1454 soc_pcm_ops.silence = platform->pcm_ops->silence;
@@ -1906,18 +2018,22 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1906{ 2018{
1907 struct soc_mixer_control *mc = 2019 struct soc_mixer_control *mc =
1908 (struct soc_mixer_control *)kcontrol->private_value; 2020 (struct soc_mixer_control *)kcontrol->private_value;
1909 int max = mc->max; 2021 int platform_max;
1910 unsigned int shift = mc->shift; 2022 unsigned int shift = mc->shift;
1911 unsigned int rshift = mc->rshift; 2023 unsigned int rshift = mc->rshift;
1912 2024
1913 if (max == 1 && !strstr(kcontrol->id.name, " Volume")) 2025 if (!mc->platform_max)
2026 mc->platform_max = mc->max;
2027 platform_max = mc->platform_max;
2028
2029 if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
1914 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 2030 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1915 else 2031 else
1916 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2032 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1917 2033
1918 uinfo->count = shift == rshift ? 1 : 2; 2034 uinfo->count = shift == rshift ? 1 : 2;
1919 uinfo->value.integer.min = 0; 2035 uinfo->value.integer.min = 0;
1920 uinfo->value.integer.max = max; 2036 uinfo->value.integer.max = platform_max;
1921 return 0; 2037 return 0;
1922} 2038}
1923EXPORT_SYMBOL_GPL(snd_soc_info_volsw); 2039EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
@@ -2015,16 +2131,20 @@ int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
2015{ 2131{
2016 struct soc_mixer_control *mc = 2132 struct soc_mixer_control *mc =
2017 (struct soc_mixer_control *)kcontrol->private_value; 2133 (struct soc_mixer_control *)kcontrol->private_value;
2018 int max = mc->max; 2134 int platform_max;
2019 2135
2020 if (max == 1 && !strstr(kcontrol->id.name, " Volume")) 2136 if (!mc->platform_max)
2137 mc->platform_max = mc->max;
2138 platform_max = mc->platform_max;
2139
2140 if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
2021 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 2141 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2022 else 2142 else
2023 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2143 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2024 2144
2025 uinfo->count = 2; 2145 uinfo->count = 2;
2026 uinfo->value.integer.min = 0; 2146 uinfo->value.integer.min = 0;
2027 uinfo->value.integer.max = max; 2147 uinfo->value.integer.max = platform_max;
2028 return 0; 2148 return 0;
2029} 2149}
2030EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); 2150EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
@@ -2125,13 +2245,17 @@ int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
2125{ 2245{
2126 struct soc_mixer_control *mc = 2246 struct soc_mixer_control *mc =
2127 (struct soc_mixer_control *)kcontrol->private_value; 2247 (struct soc_mixer_control *)kcontrol->private_value;
2128 int max = mc->max; 2248 int platform_max;
2129 int min = mc->min; 2249 int min = mc->min;
2130 2250
2251 if (!mc->platform_max)
2252 mc->platform_max = mc->max;
2253 platform_max = mc->platform_max;
2254
2131 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2255 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2132 uinfo->count = 2; 2256 uinfo->count = 2;
2133 uinfo->value.integer.min = 0; 2257 uinfo->value.integer.min = 0;
2134 uinfo->value.integer.max = max-min; 2258 uinfo->value.integer.max = platform_max - min;
2135 return 0; 2259 return 0;
2136} 2260}
2137EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8); 2261EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8);
@@ -2190,6 +2314,45 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
2190EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); 2314EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2191 2315
2192/** 2316/**
2317 * snd_soc_limit_volume - Set new limit to an existing volume control.
2318 *
2319 * @codec: where to look for the control
2320 * @name: Name of the control
2321 * @max: new maximum limit
2322 *
2323 * Return 0 for success, else error.
2324 */
2325int snd_soc_limit_volume(struct snd_soc_codec *codec,
2326 const char *name, int max)
2327{
2328 struct snd_card *card = codec->card;
2329 struct snd_kcontrol *kctl;
2330 struct soc_mixer_control *mc;
2331 int found = 0;
2332 int ret = -EINVAL;
2333
2334 /* Sanity check for name and max */
2335 if (unlikely(!name || max <= 0))
2336 return -EINVAL;
2337
2338 list_for_each_entry(kctl, &card->controls, list) {
2339 if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) {
2340 found = 1;
2341 break;
2342 }
2343 }
2344 if (found) {
2345 mc = (struct soc_mixer_control *)kctl->private_value;
2346 if (max <= mc->max) {
2347 mc->platform_max = max;
2348 ret = 0;
2349 }
2350 }
2351 return ret;
2352}
2353EXPORT_SYMBOL_GPL(snd_soc_limit_volume);
2354
2355/**
2193 * snd_soc_dai_set_sysclk - configure DAI system or master clock. 2356 * snd_soc_dai_set_sysclk - configure DAI system or master clock.
2194 * @dai: DAI 2357 * @dai: DAI
2195 * @clk_id: DAI specific clock ID 2358 * @clk_id: DAI specific clock ID