Commit bd26974f authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/dapm' into asoc-next

parents aa38bff8 c42c5ac4
...@@ -2884,7 +2884,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, ...@@ -2884,7 +2884,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
{ {
int i, r, ret = 0; int i, r, ret = 0;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
r = snd_soc_dapm_add_route(dapm, route); r = snd_soc_dapm_add_route(dapm, route);
if (r < 0) { if (r < 0) {
...@@ -2915,7 +2915,7 @@ int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, ...@@ -2915,7 +2915,7 @@ int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
{ {
int i; int i;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
snd_soc_dapm_del_route(dapm, route); snd_soc_dapm_del_route(dapm, route);
route++; route++;
...@@ -3778,18 +3778,27 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol, ...@@ -3778,18 +3778,27 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
int snd_soc_dapm_new_pcm(struct snd_soc_card *card, static void
const struct snd_soc_pcm_stream *params, snd_soc_dapm_free_kcontrol(struct snd_soc_card *card,
unsigned int num_params, unsigned long *private_value,
struct snd_soc_dapm_widget *source, int num_params,
struct snd_soc_dapm_widget *sink) const char **w_param_text)
{
int count;
devm_kfree(card->dev, (void *)*private_value);
for (count = 0 ; count < num_params; count++)
devm_kfree(card->dev, (void *)w_param_text[count]);
devm_kfree(card->dev, w_param_text);
}
static struct snd_kcontrol_new *
snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card,
char *link_name,
const struct snd_soc_pcm_stream *params,
int num_params, const char **w_param_text,
unsigned long *private_value)
{ {
struct snd_soc_dapm_widget template;
struct snd_soc_dapm_widget *w;
char *link_name;
int ret, count;
unsigned long private_value;
const char **w_param_text;
struct soc_enum w_param_enum[] = { struct soc_enum w_param_enum[] = {
SOC_ENUM_SINGLE(0, 0, 0, NULL), SOC_ENUM_SINGLE(0, 0, 0, NULL),
}; };
...@@ -3798,19 +3807,9 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, ...@@ -3798,19 +3807,9 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
snd_soc_dapm_dai_link_get, snd_soc_dapm_dai_link_get,
snd_soc_dapm_dai_link_put), snd_soc_dapm_dai_link_put),
}; };
struct snd_kcontrol_new *kcontrol_news;
const struct snd_soc_pcm_stream *config = params; const struct snd_soc_pcm_stream *config = params;
int count;
w_param_text = devm_kcalloc(card->dev, num_params,
sizeof(char *), GFP_KERNEL);
if (!w_param_text)
return -ENOMEM;
link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s",
source->name, sink->name);
if (!link_name) {
ret = -ENOMEM;
goto outfree_w_param;
}
for (count = 0 ; count < num_params; count++) { for (count = 0 ; count < num_params; count++) {
if (!config->stream_name) { if (!config->stream_name) {
...@@ -3821,57 +3820,94 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, ...@@ -3821,57 +3820,94 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
devm_kasprintf(card->dev, GFP_KERNEL, devm_kasprintf(card->dev, GFP_KERNEL,
"Anonymous Configuration %d", "Anonymous Configuration %d",
count); count);
if (!w_param_text[count]) {
ret = -ENOMEM;
goto outfree_link_name;
}
} else { } else {
w_param_text[count] = devm_kmemdup(card->dev, w_param_text[count] = devm_kmemdup(card->dev,
config->stream_name, config->stream_name,
strlen(config->stream_name) + 1, strlen(config->stream_name) + 1,
GFP_KERNEL); GFP_KERNEL);
if (!w_param_text[count]) {
ret = -ENOMEM;
goto outfree_link_name;
}
} }
if (!w_param_text[count])
goto outfree_w_param;
config++; config++;
} }
w_param_enum[0].items = num_params; w_param_enum[0].items = num_params;
w_param_enum[0].texts = w_param_text; w_param_enum[0].texts = w_param_text;
memset(&template, 0, sizeof(template)); *private_value =
template.reg = SND_SOC_NOPM;
template.id = snd_soc_dapm_dai_link;
template.name = link_name;
template.event = snd_soc_dai_link_event;
template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD;
template.num_kcontrols = 1;
/* duplicate w_param_enum on heap so that memory persists */
private_value =
(unsigned long) devm_kmemdup(card->dev, (unsigned long) devm_kmemdup(card->dev,
(void *)(kcontrol_dai_link[0].private_value), (void *)(kcontrol_dai_link[0].private_value),
sizeof(struct soc_enum), GFP_KERNEL); sizeof(struct soc_enum), GFP_KERNEL);
if (!private_value) { if (!*private_value) {
dev_err(card->dev, "ASoC: Failed to create control for %s widget\n", dev_err(card->dev, "ASoC: Failed to create control for %s widget\n",
link_name); link_name);
ret = -ENOMEM; goto outfree_w_param;
goto outfree_link_name;
} }
kcontrol_dai_link[0].private_value = private_value; kcontrol_dai_link[0].private_value = *private_value;
/* duplicate kcontrol_dai_link on heap so that memory persists */ /* duplicate kcontrol_dai_link on heap so that memory persists */
template.kcontrol_news = kcontrol_news = devm_kmemdup(card->dev, &kcontrol_dai_link[0],
devm_kmemdup(card->dev, &kcontrol_dai_link[0],
sizeof(struct snd_kcontrol_new), sizeof(struct snd_kcontrol_new),
GFP_KERNEL); GFP_KERNEL);
if (!template.kcontrol_news) { if (!kcontrol_news) {
dev_err(card->dev, "ASoC: Failed to create control for %s widget\n", dev_err(card->dev, "ASoC: Failed to create control for %s widget\n",
link_name); link_name);
ret = -ENOMEM; goto outfree_w_param;
goto outfree_private_value;
} }
return kcontrol_news;
outfree_w_param:
snd_soc_dapm_free_kcontrol(card, private_value, num_params, w_param_text);
return NULL;
}
int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
const struct snd_soc_pcm_stream *params,
unsigned int num_params,
struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_dapm_widget template;
struct snd_soc_dapm_widget *w;
const char **w_param_text;
unsigned long private_value;
char *link_name;
int ret;
link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s",
source->name, sink->name);
if (!link_name)
return -ENOMEM;
memset(&template, 0, sizeof(template));
template.reg = SND_SOC_NOPM;
template.id = snd_soc_dapm_dai_link;
template.name = link_name;
template.event = snd_soc_dai_link_event;
template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD;
template.kcontrol_news = NULL;
/* allocate memory for control, only in case of multiple configs */
if (num_params > 1) {
w_param_text = devm_kcalloc(card->dev, num_params,
sizeof(char *), GFP_KERNEL);
if (!w_param_text) {
ret = -ENOMEM;
goto param_fail;
}
template.num_kcontrols = 1;
template.kcontrol_news =
snd_soc_dapm_alloc_kcontrol(card,
link_name, params, num_params,
w_param_text, &private_value);
if (!template.kcontrol_news) {
ret = -ENOMEM;
goto param_fail;
}
} else {
w_param_text = NULL;
}
dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name); dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name);
w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template); w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template);
...@@ -3903,15 +3939,9 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, ...@@ -3903,15 +3939,9 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
devm_kfree(card->dev, w); devm_kfree(card->dev, w);
outfree_kcontrol_news: outfree_kcontrol_news:
devm_kfree(card->dev, (void *)template.kcontrol_news); devm_kfree(card->dev, (void *)template.kcontrol_news);
outfree_private_value: snd_soc_dapm_free_kcontrol(card, &private_value, num_params, w_param_text);
devm_kfree(card->dev, (void *)private_value); param_fail:
outfree_link_name:
devm_kfree(card->dev, link_name); devm_kfree(card->dev, link_name);
outfree_w_param:
for (count = 0 ; count < num_params; count++)
devm_kfree(card->dev, (void *)w_param_text[count]);
devm_kfree(card->dev, w_param_text);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment