ASoC: Add support for sequencing within
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sat, 15 Jan 2011 13:40:50 +0000 (13:40 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 19 Jan 2011 13:02:32 +0000 (13:02 +0000)
With larger devices there may be many widgets of the same type in series
in an audio path. Allow drivers to specify an additional level of ordering
within each widget type by adding a subsequence number to widgets and then
splitting operations on widgets so that widgets of the same type but
different sequence numbers are processed separately.  A typical example
would be a supply widget which requires that another widget be enabled
to provide power or clocking.

SND_SOC_DAPM_PGA_S() and SND_SOC_DAPM_SUPPLY_S() macros are provided
allowing this to be used with PGAs and supplies as these are the most
commonly affected widgets.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
include/sound/soc-dapm.h
sound/soc/soc-dapm.c

index 8031769ac48584c3ae91c30261fe8f6099bfb35b..a3760c93a8a3b76cb03e726ba8007bd2a20e458a 100644 (file)
        .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1, \
        .event = wevent, .event_flags = wflags}
 
+/* additional sequencing control within an event type */
+#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, wcontrols, \
+       wncontrols, wevent, wflags) \
+{      .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
+       .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
+       .event = wevent, .event_flags = wflags, .subseq = wsubseq}
+#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
+       wflags) \
+{      .id = snd_soc_dapm_supply, .name = wname, .reg = wreg,  \
+       .shift = wshift, .invert = winvert, .event = wevent, \
+       .event_flags = wflags, .subseq = wsubseq}
+
 /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
 #define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
        wevent, wflags) \
@@ -450,6 +462,7 @@ struct snd_soc_dapm_widget {
        unsigned char ext:1;                    /* has external widgets */
        unsigned char force:1;                  /* force state */
        unsigned char ignore_suspend:1;         /* kept enabled over suspend */
+       int subseq;                             /* sort within widget type */
 
        int (*power_check)(struct snd_soc_dapm_widget *w);
 
index 57e1c9f71149a87ad0152ae7faf326febe81b6ec..eb7436c7acad186b2a4863a81699f95eeace4808 100644 (file)
@@ -737,6 +737,12 @@ static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
 
        if (sort[a->id] != sort[b->id])
                return sort[a->id] - sort[b->id];
+       if (a->subseq != b->subseq) {
+               if (power_up)
+                       return a->subseq - b->subseq;
+               else
+                       return b->subseq - a->subseq;
+       }
        if (a->reg != b->reg)
                return a->reg - b->reg;
        if (a->dapm != b->dapm)
@@ -869,6 +875,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
        struct snd_soc_dapm_widget *w, *n;
        LIST_HEAD(pending);
        int cur_sort = -1;
+       int cur_subseq = -1;
        int cur_reg = SND_SOC_NOPM;
        struct snd_soc_dapm_context *cur_dapm = NULL;
        int ret;
@@ -884,12 +891,13 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
 
                /* Do we need to apply any queued changes? */
                if (sort[w->id] != cur_sort || w->reg != cur_reg ||
-                   w->dapm != cur_dapm) {
+                   w->dapm != cur_dapm || w->subseq != cur_subseq) {
                        if (!list_empty(&pending))
                                dapm_seq_run_coalesced(cur_dapm, &pending);
 
                        INIT_LIST_HEAD(&pending);
                        cur_sort = -1;
+                       cur_subseq = -1;
                        cur_reg = SND_SOC_NOPM;
                        cur_dapm = NULL;
                }
@@ -934,6 +942,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
                default:
                        /* Queue it up for application */
                        cur_sort = sort[w->id];
+                       cur_subseq = w->subseq;
                        cur_reg = w->reg;
                        cur_dapm = w->dapm;
                        list_move(&w->power_list, &pending);