[alsa-devel] [PATCH 1/5] ASoC: dapm: Add snd_soc_dapm_switch to the power up/down sequence table
The power up/down sequence order for DAPM switch widgets is not explicitly initialized, causing them to be run always as the first widget type for both power up and down. Move it to the same position in the sequence as other mixer widget types.
Cc: stable@vger.kernel.org Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/soc-dapm.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 2201f22..10290c7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -64,6 +64,7 @@ static int dapm_up_seq[] = { [snd_soc_dapm_virt_mux] = 5, [snd_soc_dapm_value_mux] = 5, [snd_soc_dapm_dac] = 6, + [snd_soc_dapm_switch] = 7, [snd_soc_dapm_mixer] = 7, [snd_soc_dapm_mixer_named_ctl] = 7, [snd_soc_dapm_pga] = 8, @@ -83,6 +84,7 @@ static int dapm_down_seq[] = { [snd_soc_dapm_line] = 2, [snd_soc_dapm_out_drv] = 2, [snd_soc_dapm_pga] = 4, + [snd_soc_dapm_switch] = 5, [snd_soc_dapm_mixer_named_ctl] = 5, [snd_soc_dapm_mixer] = 5, [snd_soc_dapm_dac] = 6,
The private data containing the widget list that is a assigned to a DAPM kcontrol is never freed. Setup the private_free for DAPM kcontrols to take care of this.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/soc-dapm.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 10290c7..f81d942 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -509,6 +509,11 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, return 0; }
+static void dapm_kcontrol_free(struct snd_kcontrol *kctl) +{ + kfree(kctl->private_data); +} + /* * Determine if a kcontrol is shared. If it is, look it up. If it isn't, * create it. Either way, add the widget into the control's widget list @@ -615,6 +620,7 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, prefix); + kcontrol->private_free = dapm_kcontrol_free; ret = snd_ctl_add(card, kcontrol); if (ret < 0) { dev_err(dapm->dev,
The condition 'i == item' is only true when, well, 'i' equals 'item'. So just use 'item' directly as the index into the array.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/soc-dapm.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f81d942..6d4a72e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -367,11 +367,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, val = soc_widget_read(w, e->reg); item = (val >> e->shift_l) & e->mask;
- p->connect = 0; - for (i = 0; i < e->max; i++) { - if (!(strcmp(p->name, e->texts[i])) && item == i) - p->connect = 1; - } + if (item < e->max && !strcmp(p->name, e->texts[item])) + p->connect = 1; + else + p->connect = 0; } break; case snd_soc_dapm_virt_mux: { @@ -401,11 +400,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, break; }
- p->connect = 0; - for (i = 0; i < e->max; i++) { - if (!(strcmp(p->name, e->texts[i])) && item == i) - p->connect = 1; - } + if (item < e->max && !strcmp(p->name, e->texts[item])) + p->connect = 1; + else + p->connect = 0; } break; /* does not affect routing - always connected */
We have the same code for freeing a DAPM path in three different locations. Introduce a new helper function to take care of this.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/soc-dapm.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6d4a72e..a771473 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2109,6 +2109,15 @@ static void snd_soc_dapm_sys_remove(struct device *dev) device_remove_file(dev, &dev_attr_dapm_widget); }
+static void dapm_free_path(struct snd_soc_dapm_path *path) +{ + list_del(&path->list_sink); + list_del(&path->list_source); + list_del(&path->list); + kfree(path->long_name); + kfree(path); +} + /* free all dapm widgets and resources */ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) { @@ -2124,20 +2133,12 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) * While removing the path, remove reference to it from both * source and sink widgets so that path is removed only once. */ - list_for_each_entry_safe(p, next_p, &w->sources, list_sink) { - list_del(&p->list_sink); - list_del(&p->list_source); - list_del(&p->list); - kfree(p->long_name); - kfree(p); - } - list_for_each_entry_safe(p, next_p, &w->sinks, list_source) { - list_del(&p->list_sink); - list_del(&p->list_source); - list_del(&p->list); - kfree(p->long_name); - kfree(p); - } + list_for_each_entry_safe(p, next_p, &w->sources, list_sink) + dapm_free_path(p); + + list_for_each_entry_safe(p, next_p, &w->sinks, list_source) + dapm_free_path(p); + kfree(w->kcontrols); kfree(w->name); kfree(w); @@ -2413,10 +2414,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, dapm_mark_dirty(path->source, "Route removed"); dapm_mark_dirty(path->sink, "Route removed");
- list_del(&path->list); - list_del(&path->list_sink); - list_del(&path->list_source); - kfree(path); + dapm_free_path(path); } else { dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n", source, sink);
Since commit 85762e71 ("ASoC: dapm: Implement mixer control sharing") the long_name field of the snd_soc_dapm_path struct is unused. All of the name handling now happens entirely in dapm_create_or_share_mixmux_kcontrol(). So we can remove the long_name field from the snd_soc_dapm_path struct.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- include/sound/soc-dapm.h | 1 - sound/soc/soc-dapm.c | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 69e8e07..3e479f4 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -481,7 +481,6 @@ struct snd_soc_dapm_route { /* dapm audio path between two widgets */ struct snd_soc_dapm_path { const char *name; - const char *long_name;
/* source (input) and sink (output) widgets */ struct snd_soc_dapm_widget *source; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a771473..b941908 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -619,17 +619,15 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, prefix); kcontrol->private_free = dapm_kcontrol_free; + kfree(long_name); ret = snd_ctl_add(card, kcontrol); if (ret < 0) { dev_err(dapm->dev, "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", w->name, name, ret); kfree(wlist); - kfree(long_name); return ret; } - - path->long_name = long_name; }
kcontrol->private_data = wlist; @@ -2114,7 +2112,6 @@ static void dapm_free_path(struct snd_soc_dapm_path *path) list_del(&path->list_sink); list_del(&path->list_source); list_del(&path->list); - kfree(path->long_name); kfree(path); }
On Fri, Jun 14, 2013 at 01:16:50PM +0200, Lars-Peter Clausen wrote:
The power up/down sequence order for DAPM switch widgets is not explicitly initialized, causing them to be run always as the first widget type for both power up and down. Move it to the same position in the sequence as other mixer widget types.
Applied all, thanks.
Cc: stable@vger.kernel.org
but this seems a bit hasty - there are existing users of this who haven't been complianing, changing the sequencing underneath them may cause some unintended breakage if they've somehow been relying on the existing behaviour. It doesn't seem safe enough for a stable fix, people ought to be able to blindly take the stable kernel updates.
participants (2)
-
Lars-Peter Clausen
-
Mark Brown