ASoC: twl6040: Add ramp up/down volume for HS and HF
[deliverable/linux.git] / sound / soc / soc-dapm.c
index 450307ccaf68db4b4586bd69496e16d172b16799..6a29d59dabaf22b9f5e4c1b38381bb0208308ba1 100644 (file)
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
-#include <sound/soc-dapm.h>
 #include <sound/initval.h>
 
+#include <trace/events/asoc.h>
+
 /* dapm power sequences - make this per codec in the future */
 static int dapm_up_seq[] = {
        [snd_soc_dapm_pre] = 0,
@@ -151,6 +152,8 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card,
                return -EINVAL;
        }
 
+       trace_snd_soc_bias_level_start(card, level);
+
        if (card && card->set_bias_level)
                ret = card->set_bias_level(card, level);
        if (ret == 0) {
@@ -160,6 +163,8 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card,
                        dapm->bias_level = level;
        }
 
+       trace_snd_soc_bias_level_done(card, level);
+
        return ret;
 }
 
@@ -700,12 +705,12 @@ static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
                            struct snd_soc_dapm_widget *b,
                            int sort[])
 {
-       if (a->codec != b->codec)
-               return (unsigned long)a - (unsigned long)b;
        if (sort[a->id] != sort[b->id])
                return sort[a->id] - sort[b->id];
        if (a->reg != b->reg)
                return a->reg - b->reg;
+       if (a->dapm != b->dapm)
+               return (unsigned long)a->dapm - (unsigned long)b->dapm;
 
        return 0;
 }
@@ -726,13 +731,57 @@ static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
        list_add_tail(&new_widget->power_list, list);
 }
 
+static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm,
+                                struct snd_soc_dapm_widget *w, int event)
+{
+       struct snd_soc_card *card = dapm->card;
+       const char *ev_name;
+       int power, ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               ev_name = "PRE_PMU";
+               power = 1;
+               break;
+       case SND_SOC_DAPM_POST_PMU:
+               ev_name = "POST_PMU";
+               power = 1;
+               break;
+       case SND_SOC_DAPM_PRE_PMD:
+               ev_name = "PRE_PMD";
+               power = 0;
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               ev_name = "POST_PMD";
+               power = 0;
+               break;
+       default:
+               BUG();
+               return;
+       }
+
+       if (w->power != power)
+               return;
+
+       if (w->event && (w->event_flags & event)) {
+               pop_dbg(dapm->dev, card->pop_time, "pop test : %s %s\n",
+                       w->name, ev_name);
+               trace_snd_soc_dapm_widget_event_start(w, event);
+               ret = w->event(w, NULL, event);
+               trace_snd_soc_dapm_widget_event_done(w, event);
+               if (ret < 0)
+                       pr_err("%s: %s event failed: %d\n",
+                              ev_name, w->name, ret);
+       }
+}
+
 /* Apply the coalesced changes from a DAPM sequence */
 static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
                                   struct list_head *pending)
 {
-       struct snd_soc_dapm_widget *w;
        struct snd_soc_card *card = dapm->card;
-       int reg, power, ret;
+       struct snd_soc_dapm_widget *w;
+       int reg, power;
        unsigned int value = 0;
        unsigned int mask = 0;
        unsigned int cur_mask;
@@ -757,29 +806,9 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
                        "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
                        w->name, reg, value, mask);
 
-               /* power up pre event */
-               if (w->power && w->event &&
-                   (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
-                       pop_dbg(dapm->dev, card->pop_time,
-                               "pop test : %s PRE_PMU\n", w->name);
-                       ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
-                       if (ret < 0)
-                               dev_err(dapm->dev,
-                                       "%s: pre event failed: %d\n",
-                                       w->name, ret);
-               }
-
-               /* power down pre event */
-               if (!w->power && w->event &&
-                   (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
-                       pop_dbg(dapm->dev, card->pop_time,
-                               "pop test : %s PRE_PMD\n", w->name);
-                       ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
-                       if (ret < 0)
-                               dev_err(dapm->dev,
-                                       "%s: pre event failed: %d\n",
-                                       w->name, ret);
-               }
+               /* Check for events */
+               dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMU);
+               dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMD);
        }
 
        if (reg >= 0) {
@@ -791,30 +820,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
        }
 
        list_for_each_entry(w, pending, power_list) {
-               /* power up post event */
-               if (w->power && w->event &&
-                   (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
-                       pop_dbg(dapm->dev, card->pop_time,
-                               "pop test : %s POST_PMU\n", w->name);
-                       ret = w->event(w,
-                                      NULL, SND_SOC_DAPM_POST_PMU);
-                       if (ret < 0)
-                               dev_err(dapm->dev,
-                                       "%s: post event failed: %d\n",
-                                       w->name, ret);
-               }
-
-               /* power down post event */
-               if (!w->power && w->event &&
-                   (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
-                       pop_dbg(dapm->dev, card->pop_time,
-                               "pop test : %s POST_PMD\n", w->name);
-                       ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
-                       if (ret < 0)
-                               dev_err(dapm->dev,
-                                       "%s: post event failed: %d\n",
-                                       w->name, ret);
-               }
+               dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMU);
+               dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMD);
        }
 }
 
@@ -921,6 +928,8 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
        int power;
        int sys_power = 0;
 
+       trace_snd_soc_dapm_start(card);
+
        /* Check which widgets we need to power and store them in
         * lists indicating if they should be powered up or down.
         */
@@ -947,6 +956,8 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                        if (w->power == power)
                                continue;
 
+                       trace_snd_soc_dapm_widget_power(w, power);
+
                        if (power)
                                dapm_seq_insert(w, &up_list, dapm_up_seq);
                        else
@@ -1037,6 +1048,8 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                "DAPM sequencing finished, waiting %dms\n", card->pop_time);
        pop_wait(card->pop_time);
 
+       trace_snd_soc_dapm_done(card);
+
        return 0;
 }
 
@@ -1281,6 +1294,7 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
 
        list_for_each_entry_safe(w, next_w, &dapm->widgets, list) {
                list_del(&w->list);
+               kfree(w->name);
                kfree(w);
        }
 
@@ -1332,11 +1346,25 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
 {
        struct snd_soc_dapm_path *path;
        struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
-       const char *sink = route->sink;
+       const char *sink;
        const char *control = route->control;
-       const char *source = route->source;
+       const char *source;
+       char prefixed_sink[80];
+       char prefixed_source[80];
        int ret = 0;
 
+       if (dapm->codec->name_prefix) {
+               snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
+                        dapm->codec->name_prefix, route->sink);
+               sink = prefixed_sink;
+               snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
+                        dapm->codec->name_prefix, route->source);
+               source = prefixed_source;
+       } else {
+               sink = route->sink;
+               source = route->source;
+       }
+
        /* find src and dest widgets */
        list_for_each_entry(w, &dapm->widgets, list) {
 
@@ -1964,10 +1992,25 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
        const struct snd_soc_dapm_widget *widget)
 {
        struct snd_soc_dapm_widget *w;
+       size_t name_len;
 
        if ((w = dapm_cnew_widget(widget)) == NULL)
                return -ENOMEM;
 
+       name_len = strlen(widget->name) + 1;
+       if (dapm->codec->name_prefix)
+               name_len += 1 + strlen(dapm->codec->name_prefix);
+       w->name = kmalloc(name_len, GFP_KERNEL);
+       if (w->name == NULL) {
+               kfree(w);
+               return -ENOMEM;
+       }
+       if (dapm->codec->name_prefix)
+               snprintf(w->name, name_len, "%s %s",
+                       dapm->codec->name_prefix, widget->name);
+       else
+               snprintf(w->name, name_len, "%s", widget->name);
+
        w->dapm = dapm;
        w->codec = dapm->codec;
        INIT_LIST_HEAD(&w->sources);
This page took 0.036227 seconds and 5 git commands to generate.