ASoC: twl6040: Add ramp up/down volume for HS and HF
[deliverable/linux.git] / sound / soc / soc-dapm.c
index b8f653eaffaa059833bdfc7f572bd4566b41efac..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,
@@ -91,17 +92,24 @@ static void pop_wait(u32 pop_time)
                schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
 }
 
-static void pop_dbg(u32 pop_time, const char *fmt, ...)
+static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
 {
        va_list args;
+       char *buf;
 
-       va_start(args, fmt);
+       if (!pop_time)
+               return;
 
-       if (pop_time) {
-               vprintk(fmt, args);
-       }
+       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (buf == NULL)
+               return;
 
+       va_start(args, fmt);
+       vsnprintf(buf, PAGE_SIZE, fmt, args);
+       dev_info(dev, buf);
        va_end(args);
+
+       kfree(buf);
 }
 
 /* create a new dapm widget */
@@ -144,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) {
@@ -153,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;
 }
 
@@ -293,6 +305,7 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
        unsigned int old, new;
        struct snd_soc_codec *codec = widget->codec;
        struct snd_soc_dapm_context *dapm = widget->dapm;
+       struct snd_soc_card *card = dapm->card;
 
        /* check for valid widgets */
        if (widget->reg < 0 || widget->id == snd_soc_dapm_input ||
@@ -312,14 +325,15 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
 
        change = old != new;
        if (change) {
-               pop_dbg(dapm->pop_time, "pop test %s : %s in %d ms\n",
+               pop_dbg(dapm->dev, card->pop_time,
+                       "pop test %s : %s in %d ms\n",
                        widget->name, widget->power ? "on" : "off",
-                       dapm->pop_time);
-               pop_wait(dapm->pop_time);
+                       card->pop_time);
+               pop_wait(card->pop_time);
                snd_soc_write(codec, widget->reg, new);
        }
-       pr_debug("reg %x old %x new %x change %d\n", widget->reg,
-                old, new, change);
+       dev_dbg(dapm->dev, "reg %x old %x new %x change %d\n", widget->reg,
+               old, new, change);
        return change;
 }
 
@@ -374,9 +388,9 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm,
                                path->long_name);
                        ret = snd_ctl_add(card, path->kcontrol);
                        if (ret < 0) {
-                               printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n",
-                                      path->long_name,
-                                      ret);
+                               dev_err(dapm->dev,
+                                       "asoc: failed to add dapm kcontrol %s: %d\n",
+                                       path->long_name, ret);
                                kfree(path->long_name);
                                path->long_name = NULL;
                                return ret;
@@ -396,7 +410,7 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm,
        int ret = 0;
 
        if (!w->num_kcontrols) {
-               printk(KERN_ERR "asoc: mux %s has no controls\n", w->name);
+               dev_err(dapm->dev, "asoc: mux %s has no controls\n", w->name);
                return -EINVAL;
        }
 
@@ -412,7 +426,7 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm,
        return ret;
 
 err:
-       printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
+       dev_err(dapm->dev, "asoc: failed to add kcontrol %s\n", w->name);
        return ret;
 }
 
@@ -421,7 +435,8 @@ static int dapm_new_pga(struct snd_soc_dapm_context *dapm,
        struct snd_soc_dapm_widget *w)
 {
        if (w->num_kcontrols)
-               pr_err("asoc: PGA controls not supported: '%s'\n", w->name);
+               dev_err(w->dapm->dev,
+                       "asoc: PGA controls not supported: '%s'\n", w->name);
 
        return 0;
 }
@@ -447,7 +462,8 @@ static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
        case SNDRV_CTL_POWER_D3hot:
        case SNDRV_CTL_POWER_D3cold:
                if (widget->ignore_suspend)
-                       pr_debug("%s ignoring suspend\n", widget->name);
+                       dev_dbg(widget->dapm->dev, "%s ignoring suspend\n",
+                               widget->name);
                return widget->ignore_suspend;
        default:
                return 1;
@@ -578,7 +594,7 @@ static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w)
 
        /* call any power change event handlers */
        if (w->event)
-               pr_debug("power %s event for %s flags %x\n",
+               dev_dbg(w->dapm->dev, "power %s event for %s flags %x\n",
                         w->power ? "on" : "off",
                         w->name, w->event_flags);
 
@@ -689,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;
 }
@@ -715,12 +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_card *card = dapm->card;
        struct snd_soc_dapm_widget *w;
-       int reg, power, ret;
+       int reg, power;
        unsigned int value = 0;
        unsigned int mask = 0;
        unsigned int cur_mask;
@@ -741,64 +802,26 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
                if (power)
                        value |= cur_mask;
 
-               pop_dbg(dapm->pop_time,
+               pop_dbg(dapm->dev, card->pop_time,
                        "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->pop_time, "pop test : %s PRE_PMU\n",
-                               w->name);
-                       ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
-                       if (ret < 0)
-                               pr_err("%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->pop_time, "pop test : %s PRE_PMD\n",
-                               w->name);
-                       ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
-                       if (ret < 0)
-                               pr_err("%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) {
-               pop_dbg(dapm->pop_time,
+               pop_dbg(dapm->dev, card->pop_time,
                        "pop test : Applying 0x%x/0x%x to %x in %dms\n",
-                       value, mask, reg, dapm->pop_time);
-               pop_wait(dapm->pop_time);
+                       value, mask, reg, card->pop_time);
+               pop_wait(card->pop_time);
                snd_soc_update_bits(dapm->codec, reg, mask, value);
        }
 
        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->pop_time, "pop test : %s POST_PMU\n",
-                               w->name);
-                       ret = w->event(w,
-                                      NULL, SND_SOC_DAPM_POST_PMU);
-                       if (ret < 0)
-                               pr_err("%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->pop_time, "pop test : %s POST_PMD\n",
-                               w->name);
-                       ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
-                       if (ret < 0)
-                               pr_err("%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);
        }
 }
 
@@ -878,8 +901,8 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
                }
 
                if (ret < 0)
-                       pr_err("Failed to apply widget power: %d\n",
-                              ret);
+                       dev_err(w->dapm->dev,
+                               "Failed to apply widget power: %d\n", ret);
        }
 
        if (!list_empty(&pending))
@@ -905,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.
         */
@@ -931,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
@@ -973,7 +1000,8 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                ret = snd_soc_dapm_set_bias_level(card, dapm,
                                                  SND_SOC_BIAS_STANDBY);
                if (ret != 0)
-                       pr_err("Failed to turn on bias: %d\n", ret);
+                       dev_err(dapm->dev,
+                               "Failed to turn on bias: %d\n", ret);
        }
 
        /* If we're changing to all on or all off then prepare */
@@ -981,7 +1009,8 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
            (!sys_power && dapm->bias_level == SND_SOC_BIAS_ON)) {
                ret = snd_soc_dapm_set_bias_level(card, dapm, SND_SOC_BIAS_PREPARE);
                if (ret != 0)
-                       pr_err("Failed to prepare bias: %d\n", ret);
+                       dev_err(dapm->dev,
+                               "Failed to prepare bias: %d\n", ret);
        }
 
        /* Power down widgets first; try to avoid amplifying pops. */
@@ -994,7 +1023,8 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
        if (dapm->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
                ret = snd_soc_dapm_set_bias_level(card, dapm, SND_SOC_BIAS_STANDBY);
                if (ret != 0)
-                       pr_err("Failed to apply standby bias: %d\n", ret);
+                       dev_err(dapm->dev,
+                               "Failed to apply standby bias: %d\n", ret);
        }
 
        /* If we're in standby and can support bias off then do that */
@@ -1002,19 +1032,23 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
            dapm->idle_bias_off) {
                ret = snd_soc_dapm_set_bias_level(card, dapm, SND_SOC_BIAS_OFF);
                if (ret != 0)
-                       pr_err("Failed to turn off bias: %d\n", ret);
+                       dev_err(dapm->dev,
+                               "Failed to turn off bias: %d\n", ret);
        }
 
        /* If we just powered up then move to active bias */
        if (dapm->bias_level == SND_SOC_BIAS_PREPARE && sys_power) {
                ret = snd_soc_dapm_set_bias_level(card, dapm, SND_SOC_BIAS_ON);
                if (ret != 0)
-                       pr_err("Failed to apply active bias: %d\n", ret);
+                       dev_err(dapm->dev,
+                               "Failed to apply active bias: %d\n", ret);
        }
 
-       pop_dbg(dapm->pop_time, "DAPM sequencing finished, waiting %dms\n",
-               dapm->pop_time);
-       pop_wait(dapm->pop_time);
+       pop_dbg(dapm->dev, card->pop_time,
+               "DAPM sequencing finished, waiting %dms\n", card->pop_time);
+       pop_wait(card->pop_time);
+
+       trace_snd_soc_dapm_done(card);
 
        return 0;
 }
@@ -1109,9 +1143,9 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm)
                                        dapm->debugfs_dapm, w,
                                        &dapm_widget_power_fops);
                if (!d)
-                       printk(KERN_WARNING
-                              "ASoC: Failed to create %s debugfs file\n",
-                              w->name);
+                       dev_warn(w->dapm->dev,
+                               "ASoC: Failed to create %s debugfs file\n",
+                               w->name);
        }
 }
 #else
@@ -1260,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);
        }
 
@@ -1277,7 +1312,8 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
 
        list_for_each_entry(w, &dapm->widgets, list) {
                if (!strcmp(w->name, pin)) {
-                       pr_debug("dapm: %s: pin %s\n", dapm->codec->name, pin);
+                       dev_dbg(w->dapm->dev, "dapm: pin %s = %d\n",
+                               pin, status);
                        w->connected = status;
                        /* Allow disabling of forced pins */
                        if (status == 0)
@@ -1286,8 +1322,7 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
                }
        }
 
-       pr_err("dapm: %s: configuring unknown pin %s\n",
-              dapm->codec->name, pin);
+       dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
        return -EINVAL;
 }
 
@@ -1311,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) {
 
@@ -1413,8 +1462,8 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
        return 0;
 
 err:
-       printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source,
-               control, sink);
+       dev_warn(dapm->dev, "asoc: no dapm match for %s --> %s --> %s\n",
+                source, control, sink);
        kfree(path);
        return ret;
 }
@@ -1440,9 +1489,8 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
        for (i = 0; i < num; i++) {
                ret = snd_soc_dapm_add_route(dapm, route);
                if (ret < 0) {
-                       printk(KERN_ERR "Failed to add route %s->%s\n",
-                              route->source,
-                              route->sink);
+                       dev_err(dapm->dev, "Failed to add route %s->%s\n",
+                               route->source, route->sink);
                        return ret;
                }
                route++;
@@ -1944,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);
@@ -1980,9 +2043,9 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
        for (i = 0; i < num; i++) {
                ret = snd_soc_dapm_new_control(dapm, widget);
                if (ret < 0) {
-                       printk(KERN_ERR
-                              "ASoC: Failed to create DAPM control %s: %d\n",
-                              widget->name, ret);
+                       dev_err(dapm->dev,
+                               "ASoC: Failed to create DAPM control %s: %d\n",
+                               widget->name, ret);
                        return ret;
                }
                widget++;
@@ -2000,8 +2063,8 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
        {
                if (!w->sname)
                        continue;
-               pr_debug("widget %s\n %s stream %s event %d\n",
-                        w->name, w->sname, stream, event);
+               dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
+                       w->name, w->sname, stream, event);
                if (strstr(w->sname, stream)) {
                        switch(event) {
                        case SND_SOC_DAPM_STREAM_START:
@@ -2083,15 +2146,15 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
 
        list_for_each_entry(w, &dapm->widgets, list) {
                if (!strcmp(w->name, pin)) {
-                       pr_debug("dapm: %s: pin %s\n", dapm->codec->name, pin);
+                       dev_dbg(w->dapm->dev,
+                               "dapm: force enable pin %s\n", pin);
                        w->connected = 1;
                        w->force = 1;
                        return 0;
                }
        }
 
-       pr_err("dapm: %s: configuring unknown pin %s\n",
-              dapm->codec->name, pin);
+       dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
        return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
@@ -2178,7 +2241,7 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
                }
        }
 
-       pr_err("Unknown DAPM pin: %s\n", pin);
+       dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
        return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
This page took 0.035374 seconds and 5 git commands to generate.