aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c110
1 files changed, 92 insertions, 18 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index dcade130157f..dc8ff13187f7 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -371,12 +371,16 @@ static void dapm_reset(struct snd_soc_card *card)
371 } 371 }
372} 372}
373 373
374static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg) 374static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg,
375 unsigned int *value)
375{ 376{
376 if (w->codec) 377 if (w->codec) {
377 return snd_soc_read(w->codec, reg); 378 *value = snd_soc_read(w->codec, reg);
378 else if (w->platform) 379 return 0;
379 return snd_soc_platform_read(w->platform, reg); 380 } else if (w->platform) {
381 *value = snd_soc_platform_read(w->platform, reg);
382 return 0;
383 }
380 384
381 dev_err(w->dapm->dev, "ASoC: no valid widget read method\n"); 385 dev_err(w->dapm->dev, "ASoC: no valid widget read method\n");
382 return -1; 386 return -1;
@@ -430,13 +434,12 @@ static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
430 return ret; 434 return ret;
431 } else { 435 } else {
432 soc_widget_lock(w); 436 soc_widget_lock(w);
433 ret = soc_widget_read(w, reg); 437 ret = soc_widget_read(w, reg, &old);
434 if (ret < 0) { 438 if (ret < 0) {
435 soc_widget_unlock(w); 439 soc_widget_unlock(w);
436 return ret; 440 return ret;
437 } 441 }
438 442
439 old = ret;
440 new = (old & ~mask) | (value & mask); 443 new = (old & ~mask) | (value & mask);
441 change = old != new; 444 change = old != new;
442 if (change) { 445 if (change) {
@@ -513,7 +516,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
513 unsigned int invert = mc->invert; 516 unsigned int invert = mc->invert;
514 517
515 if (reg != SND_SOC_NOPM) { 518 if (reg != SND_SOC_NOPM) {
516 val = soc_widget_read(w, reg); 519 soc_widget_read(w, reg, &val);
517 val = (val >> shift) & mask; 520 val = (val >> shift) & mask;
518 if (invert) 521 if (invert)
519 val = max - val; 522 val = max - val;
@@ -529,7 +532,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
529 w->kcontrol_news[i].private_value; 532 w->kcontrol_news[i].private_value;
530 int val, item; 533 int val, item;
531 534
532 val = soc_widget_read(w, e->reg); 535 soc_widget_read(w, e->reg, &val);
533 item = (val >> e->shift_l) & e->mask; 536 item = (val >> e->shift_l) & e->mask;
534 537
535 if (item < e->max && !strcmp(p->name, e->texts[item])) 538 if (item < e->max && !strcmp(p->name, e->texts[item]))
@@ -558,7 +561,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
558 w->kcontrol_news[i].private_value; 561 w->kcontrol_news[i].private_value;
559 int val, item; 562 int val, item;
560 563
561 val = soc_widget_read(w, e->reg); 564 soc_widget_read(w, e->reg, &val);
562 val = (val >> e->shift_l) & e->mask; 565 val = (val >> e->shift_l) & e->mask;
563 for (item = 0; item < e->max; item++) { 566 for (item = 0; item < e->max; item++) {
564 if (val == e->values[item]) 567 if (val == e->values[item])
@@ -2473,7 +2476,8 @@ err:
2473} 2476}
2474 2477
2475static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, 2478static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2476 const struct snd_soc_dapm_route *route) 2479 const struct snd_soc_dapm_route *route,
2480 unsigned int is_prefixed)
2477{ 2481{
2478 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 2482 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
2479 struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL; 2483 struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
@@ -2483,7 +2487,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2483 char prefixed_source[80]; 2487 char prefixed_source[80];
2484 int ret; 2488 int ret;
2485 2489
2486 if (dapm->codec && dapm->codec->name_prefix) { 2490 if (dapm->codec && dapm->codec->name_prefix && !is_prefixed) {
2487 snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", 2491 snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2488 dapm->codec->name_prefix, route->sink); 2492 dapm->codec->name_prefix, route->sink);
2489 sink = prefixed_sink; 2493 sink = prefixed_sink;
@@ -2611,7 +2615,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
2611 2615
2612 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); 2616 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2613 for (i = 0; i < num; i++) { 2617 for (i = 0; i < num; i++) {
2614 r = snd_soc_dapm_add_route(dapm, route); 2618 r = snd_soc_dapm_add_route(dapm, route, false);
2615 if (r < 0) { 2619 if (r < 0) {
2616 dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n", 2620 dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n",
2617 route->source, 2621 route->source,
@@ -2782,7 +2786,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
2782 2786
2783 /* Read the initial power state from the device */ 2787 /* Read the initial power state from the device */
2784 if (w->reg >= 0) { 2788 if (w->reg >= 0) {
2785 val = soc_widget_read(w, w->reg) >> w->shift; 2789 soc_widget_read(w, w->reg, &val);
2790 val = val >> w->shift;
2786 val &= w->mask; 2791 val &= w->mask;
2787 if (val == w->on_val) 2792 if (val == w->on_val)
2788 w->power = 1; 2793 w->power = 1;
@@ -2868,6 +2873,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2868 unsigned int val; 2873 unsigned int val;
2869 int connect, change; 2874 int connect, change;
2870 struct snd_soc_dapm_update update; 2875 struct snd_soc_dapm_update update;
2876 int ret = 0;
2871 2877
2872 if (snd_soc_volsw_is_stereo(mc)) 2878 if (snd_soc_volsw_is_stereo(mc))
2873 dev_warn(codec->dapm.dev, 2879 dev_warn(codec->dapm.dev,
@@ -2901,12 +2907,16 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2901 card->update = &update; 2907 card->update = &update;
2902 } 2908 }
2903 2909
2904 soc_dapm_mixer_update_power(card, kcontrol, connect); 2910 ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
2905 2911
2906 card->update = NULL; 2912 card->update = NULL;
2907 } 2913 }
2908 2914
2909 mutex_unlock(&card->dapm_mutex); 2915 mutex_unlock(&card->dapm_mutex);
2916
2917 if (ret > 0)
2918 soc_dpcm_runtime_update(card);
2919
2910 return change; 2920 return change;
2911} 2921}
2912EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); 2922EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
@@ -2955,6 +2965,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2955 unsigned int val, mux, change; 2965 unsigned int val, mux, change;
2956 unsigned int mask; 2966 unsigned int mask;
2957 struct snd_soc_dapm_update update; 2967 struct snd_soc_dapm_update update;
2968 int ret = 0;
2958 2969
2959 if (ucontrol->value.enumerated.item[0] > e->max - 1) 2970 if (ucontrol->value.enumerated.item[0] > e->max - 1)
2960 return -EINVAL; 2971 return -EINVAL;
@@ -2978,12 +2989,16 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2978 update.val = val; 2989 update.val = val;
2979 card->update = &update; 2990 card->update = &update;
2980 2991
2981 soc_dapm_mux_update_power(card, kcontrol, mux, e); 2992 ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
2982 2993
2983 card->update = NULL; 2994 card->update = NULL;
2984 } 2995 }
2985 2996
2986 mutex_unlock(&card->dapm_mutex); 2997 mutex_unlock(&card->dapm_mutex);
2998
2999 if (ret > 0)
3000 soc_dpcm_runtime_update(card);
3001
2987 return change; 3002 return change;
2988} 3003}
2989EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); 3004EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
@@ -3019,6 +3034,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
3019 struct soc_enum *e = 3034 struct soc_enum *e =
3020 (struct soc_enum *)kcontrol->private_value; 3035 (struct soc_enum *)kcontrol->private_value;
3021 int change; 3036 int change;
3037 int ret = 0;
3022 3038
3023 if (ucontrol->value.enumerated.item[0] >= e->max) 3039 if (ucontrol->value.enumerated.item[0] >= e->max)
3024 return -EINVAL; 3040 return -EINVAL;
@@ -3028,9 +3044,13 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
3028 value = ucontrol->value.enumerated.item[0]; 3044 value = ucontrol->value.enumerated.item[0];
3029 change = dapm_kcontrol_set_value(kcontrol, value); 3045 change = dapm_kcontrol_set_value(kcontrol, value);
3030 if (change) 3046 if (change)
3031 soc_dapm_mux_update_power(card, kcontrol, value, e); 3047 ret = soc_dapm_mux_update_power(card, kcontrol, value, e);
3032 3048
3033 mutex_unlock(&card->dapm_mutex); 3049 mutex_unlock(&card->dapm_mutex);
3050
3051 if (ret > 0)
3052 soc_dpcm_runtime_update(card);
3053
3034 return change; 3054 return change;
3035} 3055}
3036EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); 3056EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
@@ -3097,6 +3117,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
3097 unsigned int val, mux, change; 3117 unsigned int val, mux, change;
3098 unsigned int mask; 3118 unsigned int mask;
3099 struct snd_soc_dapm_update update; 3119 struct snd_soc_dapm_update update;
3120 int ret = 0;
3100 3121
3101 if (ucontrol->value.enumerated.item[0] > e->max - 1) 3122 if (ucontrol->value.enumerated.item[0] > e->max - 1)
3102 return -EINVAL; 3123 return -EINVAL;
@@ -3120,12 +3141,16 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
3120 update.val = val; 3141 update.val = val;
3121 card->update = &update; 3142 card->update = &update;
3122 3143
3123 soc_dapm_mux_update_power(card, kcontrol, mux, e); 3144 ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
3124 3145
3125 card->update = NULL; 3146 card->update = NULL;
3126 } 3147 }
3127 3148
3128 mutex_unlock(&card->dapm_mutex); 3149 mutex_unlock(&card->dapm_mutex);
3150
3151 if (ret > 0)
3152 soc_dpcm_runtime_update(card);
3153
3129 return change; 3154 return change;
3130} 3155}
3131EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); 3156EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
@@ -3614,6 +3639,55 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
3614 return 0; 3639 return 0;
3615} 3640}
3616 3641
3642void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
3643{
3644 struct snd_soc_pcm_runtime *rtd = card->rtd;
3645 struct snd_soc_dai *cpu_dai, *codec_dai;
3646 struct snd_soc_dapm_route r;
3647 int i;
3648
3649 memset(&r, 0, sizeof(r));
3650
3651 /* for each BE DAI link... */
3652 for (i = 0; i < card->num_rtd; i++) {
3653 rtd = &card->rtd[i];
3654 cpu_dai = rtd->cpu_dai;
3655 codec_dai = rtd->codec_dai;
3656
3657 /* dynamic FE links have no fixed DAI mapping */
3658 if (rtd->dai_link->dynamic)
3659 continue;
3660
3661 /* there is no point in connecting BE DAI links with dummies */
3662 if (snd_soc_dai_is_dummy(codec_dai) ||
3663 snd_soc_dai_is_dummy(cpu_dai))
3664 continue;
3665
3666 /* connect BE DAI playback if widgets are valid */
3667 if (codec_dai->playback_widget && cpu_dai->playback_widget) {
3668 r.source = cpu_dai->playback_widget->name;
3669 r.sink = codec_dai->playback_widget->name;
3670 dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
3671 cpu_dai->codec->name, r.source,
3672 codec_dai->platform->name, r.sink);
3673
3674 snd_soc_dapm_add_route(&card->dapm, &r, true);
3675 }
3676
3677 /* connect BE DAI capture if widgets are valid */
3678 if (codec_dai->capture_widget && cpu_dai->capture_widget) {
3679 r.source = codec_dai->capture_widget->name;
3680 r.sink = cpu_dai->capture_widget->name;
3681 dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
3682 codec_dai->codec->name, r.source,
3683 cpu_dai->platform->name, r.sink);
3684
3685 snd_soc_dapm_add_route(&card->dapm, &r, true);
3686 }
3687
3688 }
3689}
3690
3617static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, 3691static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
3618 int event) 3692 int event)
3619{ 3693{