From 97a05cb4ab12f55e19cf28f6ceca47bb6ed8fea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:38 +0200 Subject: [PATCH 01/13] ASoC: topology: Simplify code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using goto, when there is no controls, just do a loop when there are. Overall the check seems to be a bit redundant as num_kcontrols will only be above 0 if kcontrols are set anyway, but let's keep it, while simplifying code. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-2-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 4b166294602f..dff83d49a8f6 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -394,13 +394,9 @@ static void soc_tplg_remove_widget(struct snd_soc_component *comp, if (dobj->unload) dobj->unload(comp, dobj); - if (!w->kcontrols) - goto free_news; - - for (i = 0; w->kcontrols && i < w->num_kcontrols; i++) - snd_ctl_remove(card, w->kcontrols[i]); - -free_news: + if (w->kcontrols) + for (i = 0; i < w->num_kcontrols; i++) + snd_ctl_remove(card, w->kcontrols[i]); list_del(&dobj->list); From 7aa129706b4d6f7a2c649b359eea0336eb640feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:39 +0200 Subject: [PATCH 02/13] ASoC: topology: Do not do unnecessary dobj management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Widget kcontrols do not need to be managed as topology dynamic objects with an index and a linked list. As they are always associated with a widget which is already a topology dynamic object, thus all addition/removals of a widget will by design manage the kcontrol. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-3-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index dff83d49a8f6..bd29b40acb99 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1134,8 +1134,6 @@ static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_ sm->min = le32_to_cpu(mc->min); sm->invert = le32_to_cpu(mc->invert); sm->platform_max = le32_to_cpu(mc->platform_max); - sm->dobj.index = tplg->index; - INIT_LIST_HEAD(&sm->dobj.list); /* map io handlers */ err = soc_tplg_kcontrol_bind_io(&mc->hdr, kc, tplg); @@ -1198,7 +1196,6 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k se->items = le32_to_cpu(ec->items); se->mask = le32_to_cpu(ec->mask); - se->dobj.index = tplg->index; switch (le32_to_cpu(ec->hdr.ops.info)) { case SND_SOC_TPLG_CTL_ENUM_VALUE: @@ -1273,7 +1270,6 @@ static int soc_tplg_dapm_widget_dbytes_create(struct soc_tplg *tplg, struct snd_ kc->access = le32_to_cpu(be->hdr.access); sbe->max = le32_to_cpu(be->max); - INIT_LIST_HEAD(&sbe->dobj.list); /* map standard io handlers and check for external handlers */ err = soc_tplg_kcontrol_bind_io(&be->hdr, kc, tplg); From 8ec2a2643544ce352f012ad3d248163199d05dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:40 +0200 Subject: [PATCH 03/13] ASoC: topology: Properly initialize soc_enum values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit soc_tplg_denum_create_values() should properly set its values field. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-4-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index bd29b40acb99..15c006c47d80 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -847,6 +847,8 @@ static int soc_tplg_denum_create_values(struct soc_tplg *tplg, struct soc_enum * se->dobj.control.dvalues[i] = le32_to_cpu(ec->values[i]); } + se->items = le32_to_cpu(ec->items); + se->values = (const unsigned int *)se->dobj.control.dvalues; return 0; } From 52f4f7272c92d5be3988839a33be41b180bbc28e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:41 +0200 Subject: [PATCH 04/13] ASoC: topology: Cleanup soc_tplg_dapm_widget_dbytes_create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minor cleanups to increase readability. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-5-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 15c006c47d80..73e127975822 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1249,25 +1249,22 @@ static int soc_tplg_dapm_widget_dbytes_create(struct soc_tplg *tplg, struct snd_ be = (struct snd_soc_tplg_bytes_control *)tplg->pos; /* validate kcontrol */ - if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) + if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) return -EINVAL; sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); if (!sbe) return -ENOMEM; - tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + - le32_to_cpu(be->priv.size)); + tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + le32_to_cpu(be->priv.size)); - dev_dbg(tplg->dev, - "ASoC: adding bytes kcontrol %s with access 0x%x\n", + dev_dbg(tplg->dev, "ASoC: adding bytes kcontrol %s with access 0x%x\n", be->hdr.name, be->hdr.access); - kc->private_value = (long)sbe; kc->name = devm_kstrdup(tplg->dev, be->hdr.name, GFP_KERNEL); if (!kc->name) return -ENOMEM; + kc->private_value = (long)sbe; kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc->access = le32_to_cpu(be->hdr.access); @@ -1281,11 +1278,7 @@ static int soc_tplg_dapm_widget_dbytes_create(struct soc_tplg *tplg, struct snd_ } /* pass control to driver for optional further init */ - err = soc_tplg_control_load(tplg, kc, &be->hdr); - if (err < 0) - return err; - - return 0; + return soc_tplg_control_load(tplg, kc, &be->hdr); } static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, From 40a16442a048c5f2b4336edd4d202f1930fb9df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:42 +0200 Subject: [PATCH 05/13] ASoC: topology: Cleanup soc_tplg_dapm_widget_dmixer_create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minor cleanups to increase readability. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-6-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 73e127975822..242d8b9c2f03 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1094,43 +1094,37 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) { - struct soc_mixer_control *sm; struct snd_soc_tplg_mixer_control *mc; + struct soc_mixer_control *sm; int err; mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; /* validate kcontrol */ - if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) + if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) return -EINVAL; sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); if (!sm) return -ENOMEM; - tplg->pos += sizeof(struct snd_soc_tplg_mixer_control) + - le32_to_cpu(mc->priv.size); + tplg->pos += sizeof(struct snd_soc_tplg_mixer_control) + le32_to_cpu(mc->priv.size); - dev_dbg(tplg->dev, " adding DAPM widget mixer control %s\n", - mc->hdr.name); + dev_dbg(tplg->dev, "ASoC: adding mixer kcontrol %s with access 0x%x\n", + mc->hdr.name, mc->hdr.access); - kc->private_value = (long)sm; kc->name = devm_kstrdup(tplg->dev, mc->hdr.name, GFP_KERNEL); if (!kc->name) return -ENOMEM; + kc->private_value = (long)sm; kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc->access = le32_to_cpu(mc->hdr.access); /* we only support FL/FR channel mapping atm */ - sm->reg = tplg_chan_get_reg(tplg, mc->channel, - SNDRV_CHMAP_FL); - sm->rreg = tplg_chan_get_reg(tplg, mc->channel, - SNDRV_CHMAP_FR); - sm->shift = tplg_chan_get_shift(tplg, mc->channel, - SNDRV_CHMAP_FL); - sm->rshift = tplg_chan_get_shift(tplg, mc->channel, - SNDRV_CHMAP_FR); + sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); + sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); + sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); + sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); sm->max = le32_to_cpu(mc->max); sm->min = le32_to_cpu(mc->min); @@ -1147,17 +1141,12 @@ static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_ /* create any TLV data */ err = soc_tplg_create_tlv(tplg, kc, &mc->hdr); if (err < 0) { - dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", - mc->hdr.name); + dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); return err; } /* pass control to driver for optional further init */ - err = soc_tplg_control_load(tplg, kc, &mc->hdr); - if (err < 0) - return err; - - return 0; + return soc_tplg_control_load(tplg, kc, &mc->hdr); } static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) From d1d0262a1f5c7a543271bd5899cdb4b3ddfe054b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:43 +0200 Subject: [PATCH 06/13] ASoC: topology: Cleanup soc_tplg_dapm_widget_denum_create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minor cleanups to increase readability. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-7-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 242d8b9c2f03..6a2a8249903d 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1156,36 +1156,31 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k int err; ec = (struct snd_soc_tplg_enum_control *)tplg->pos; + /* validate kcontrol */ - if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) + if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) return -EINVAL; se = devm_kzalloc(tplg->dev, sizeof(*se), GFP_KERNEL); if (!se) return -ENOMEM; - tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + - le32_to_cpu(ec->priv.size)); + tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + le32_to_cpu(ec->priv.size)); - dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n", - ec->hdr.name); + dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", ec->hdr.name, ec->items); - kc->private_value = (long)se; kc->name = devm_kstrdup(tplg->dev, ec->hdr.name, GFP_KERNEL); if (!kc->name) return -ENOMEM; + kc->private_value = (long)se; kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc->access = le32_to_cpu(ec->hdr.access); /* we only support FL/FR channel mapping atm */ se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); - se->shift_l = tplg_chan_get_shift(tplg, ec->channel, - SNDRV_CHMAP_FL); - se->shift_r = tplg_chan_get_shift(tplg, ec->channel, - SNDRV_CHMAP_FR); + se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); + se->shift_r = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR); - se->items = le32_to_cpu(ec->items); se->mask = le32_to_cpu(ec->mask); switch (le32_to_cpu(ec->hdr.ops.info)) { @@ -1193,8 +1188,7 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: err = soc_tplg_denum_create_values(tplg, se, ec); if (err < 0) { - dev_err(tplg->dev, "ASoC: could not create values for %s\n", - ec->hdr.name); + dev_err(tplg->dev, "ASoC: could not create values for %s\n", ec->hdr.name); return err; } fallthrough; @@ -1203,8 +1197,7 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: err = soc_tplg_denum_create_texts(tplg, se, ec); if (err < 0) { - dev_err(tplg->dev, "ASoC: could not create texts for %s\n", - ec->hdr.name); + dev_err(tplg->dev, "ASoC: could not create texts for %s\n", ec->hdr.name); return err; } break; @@ -1222,11 +1215,7 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k } /* pass control to driver for optional further init */ - err = soc_tplg_control_load(tplg, kc, &ec->hdr); - if (err < 0) - return err; - - return 0; + return soc_tplg_control_load(tplg, kc, &ec->hdr); } static int soc_tplg_dapm_widget_dbytes_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) From 963942f73b02b053f97e079ed6dae5f3602cc4b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:44 +0200 Subject: [PATCH 07/13] ASoC: topology: Correctly set shift_r in soc_tplg_denum_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This aligns soc_tplg_denum_create() with soc_tplg_dapm_widget_denum_create(), as there is no reason for difference in behavior. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-8-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 6a2a8249903d..e6eb514de569 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -891,7 +891,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size) se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_r = tplg_chan_get_shift(tplg, ec->channel, - SNDRV_CHMAP_FL); + SNDRV_CHMAP_FR); se->mask = le32_to_cpu(ec->mask); se->dobj.index = tplg->index; From f14a33fcadbacc1d9728e9c75253145ae6e09bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:45 +0200 Subject: [PATCH 08/13] ASoC: topology: Align dynamic object initialization for controls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit soc_tplg_dbytes_create() missed se->dobj.index initialization, so add it there. Additionally separate dynamic object initialization into separate logical block code. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-9-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index e6eb514de569..72bd3823a015 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -677,10 +677,12 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) kc.access = le32_to_cpu(be->hdr.access); sbe->max = le32_to_cpu(be->max); + + INIT_LIST_HEAD(&sbe->dobj.list); sbe->dobj.type = SND_SOC_DOBJ_BYTES; + sbe->dobj.index = tplg->index; if (tplg->ops) sbe->dobj.unload = tplg->ops->control_unload; - INIT_LIST_HEAD(&sbe->dobj.list); /* map io handlers */ ret = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, tplg); @@ -750,11 +752,12 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size) sm->min = le32_to_cpu(mc->min); sm->invert = le32_to_cpu(mc->invert); sm->platform_max = le32_to_cpu(mc->platform_max); - sm->dobj.index = tplg->index; + + INIT_LIST_HEAD(&sm->dobj.list); sm->dobj.type = SND_SOC_DOBJ_MIXER; + sm->dobj.index = tplg->index; if (tplg->ops) sm->dobj.unload = tplg->ops->control_unload; - INIT_LIST_HEAD(&sm->dobj.list); /* map io handlers */ ret = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, tplg); @@ -894,11 +897,12 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size) SNDRV_CHMAP_FR); se->mask = le32_to_cpu(ec->mask); - se->dobj.index = tplg->index; + + INIT_LIST_HEAD(&se->dobj.list); se->dobj.type = SND_SOC_DOBJ_ENUM; + se->dobj.index = tplg->index; if (tplg->ops) se->dobj.unload = tplg->ops->control_unload; - INIT_LIST_HEAD(&se->dobj.list); switch (le32_to_cpu(ec->hdr.ops.info)) { case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: From 76d8aa0f727e327a0ba9bcb904865c40d256c292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:46 +0200 Subject: [PATCH 09/13] ASoC: topology: Rename function creating widget kcontrol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In following patches it will be reused to also create standalone kcontrol, so it makes sense to name it in more generic way. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-10-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 72bd3823a015..f85cf67f74b1 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1096,7 +1096,7 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, return ret; } -static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) +static int soc_tplg_control_dmixer_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) { struct snd_soc_tplg_mixer_control *mc; struct soc_mixer_control *sm; @@ -1153,7 +1153,7 @@ static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_ return soc_tplg_control_load(tplg, kc, &mc->hdr); } -static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) +static int soc_tplg_control_denum_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) { struct snd_soc_tplg_enum_control *ec; struct soc_enum *se; @@ -1222,7 +1222,7 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k return soc_tplg_control_load(tplg, kc, &ec->hdr); } -static int soc_tplg_dapm_widget_dbytes_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) +static int soc_tplg_control_dbytes_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) { struct snd_soc_tplg_bytes_control *be; struct soc_bytes_ext *sbe; @@ -1350,7 +1350,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, kc[i].index = mixer_count; kcontrol_type[i] = SND_SOC_TPLG_TYPE_MIXER; mixer_count++; - ret = soc_tplg_dapm_widget_dmixer_create(tplg, &kc[i]); + ret = soc_tplg_control_dmixer_create(tplg, &kc[i]); if (ret < 0) goto hdr_err; break; @@ -1363,7 +1363,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, kc[i].index = enum_count; kcontrol_type[i] = SND_SOC_TPLG_TYPE_ENUM; enum_count++; - ret = soc_tplg_dapm_widget_denum_create(tplg, &kc[i]); + ret = soc_tplg_control_denum_create(tplg, &kc[i]); if (ret < 0) goto hdr_err; break; @@ -1372,7 +1372,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, kc[i].index = bytes_count; kcontrol_type[i] = SND_SOC_TPLG_TYPE_BYTES; bytes_count++; - ret = soc_tplg_dapm_widget_dbytes_create(tplg, &kc[i]); + ret = soc_tplg_control_dbytes_create(tplg, &kc[i]); if (ret < 0) goto hdr_err; break; From c2dad0db01fcacd44616e9d4c7263b187c4ff530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:47 +0200 Subject: [PATCH 10/13] ASoC: topology: Reshuffle function placement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for following cleanups move functions around. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-11-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 466 +++++++++++++++++++-------------------- 1 file changed, 233 insertions(+), 233 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index f85cf67f74b1..5aab1df7e260 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -640,6 +640,239 @@ static int soc_tplg_create_tlv(struct soc_tplg *tplg, return 0; } +static int soc_tplg_control_dmixer_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) +{ + struct snd_soc_tplg_mixer_control *mc; + struct soc_mixer_control *sm; + int err; + + mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; + + /* validate kcontrol */ + if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) + return -EINVAL; + + sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); + if (!sm) + return -ENOMEM; + + tplg->pos += sizeof(struct snd_soc_tplg_mixer_control) + le32_to_cpu(mc->priv.size); + + dev_dbg(tplg->dev, "ASoC: adding mixer kcontrol %s with access 0x%x\n", + mc->hdr.name, mc->hdr.access); + + kc->name = devm_kstrdup(tplg->dev, mc->hdr.name, GFP_KERNEL); + if (!kc->name) + return -ENOMEM; + kc->private_value = (long)sm; + kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; + kc->access = le32_to_cpu(mc->hdr.access); + + /* we only support FL/FR channel mapping atm */ + sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); + sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); + sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); + sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); + + sm->max = le32_to_cpu(mc->max); + sm->min = le32_to_cpu(mc->min); + sm->invert = le32_to_cpu(mc->invert); + sm->platform_max = le32_to_cpu(mc->platform_max); + + /* map io handlers */ + err = soc_tplg_kcontrol_bind_io(&mc->hdr, kc, tplg); + if (err) { + soc_control_err(tplg, &mc->hdr, mc->hdr.name); + return err; + } + + /* create any TLV data */ + err = soc_tplg_create_tlv(tplg, kc, &mc->hdr); + if (err < 0) { + dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); + return err; + } + + /* pass control to driver for optional further init */ + return soc_tplg_control_load(tplg, kc, &mc->hdr); +} + +static int soc_tplg_denum_create_texts(struct soc_tplg *tplg, struct soc_enum *se, + struct snd_soc_tplg_enum_control *ec) +{ + int i, ret; + + if (le32_to_cpu(ec->items) > ARRAY_SIZE(ec->texts)) + return -EINVAL; + + se->dobj.control.dtexts = + devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), sizeof(char *), GFP_KERNEL); + if (se->dobj.control.dtexts == NULL) + return -ENOMEM; + + for (i = 0; i < le32_to_cpu(ec->items); i++) { + + if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == + SNDRV_CTL_ELEM_ID_NAME_MAXLEN) { + ret = -EINVAL; + goto err; + } + + se->dobj.control.dtexts[i] = devm_kstrdup(tplg->dev, ec->texts[i], GFP_KERNEL); + if (!se->dobj.control.dtexts[i]) { + ret = -ENOMEM; + goto err; + } + } + + se->items = le32_to_cpu(ec->items); + se->texts = (const char * const *)se->dobj.control.dtexts; + return 0; + +err: + return ret; +} + +static int soc_tplg_denum_create_values(struct soc_tplg *tplg, struct soc_enum *se, + struct snd_soc_tplg_enum_control *ec) +{ + int i; + + /* + * Following "if" checks if we have at most SND_SOC_TPLG_NUM_TEXTS + * values instead of using ARRAY_SIZE(ec->values) due to the fact that + * it is oversized for its purpose. Additionally it is done so because + * it is defined in UAPI header where it can't be easily changed. + */ + if (le32_to_cpu(ec->items) > SND_SOC_TPLG_NUM_TEXTS) + return -EINVAL; + + se->dobj.control.dvalues = devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), + sizeof(*se->dobj.control.dvalues), + GFP_KERNEL); + if (!se->dobj.control.dvalues) + return -ENOMEM; + + /* convert from little-endian */ + for (i = 0; i < le32_to_cpu(ec->items); i++) { + se->dobj.control.dvalues[i] = le32_to_cpu(ec->values[i]); + } + + se->items = le32_to_cpu(ec->items); + se->values = (const unsigned int *)se->dobj.control.dvalues; + return 0; +} + +static int soc_tplg_control_denum_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) +{ + struct snd_soc_tplg_enum_control *ec; + struct soc_enum *se; + int err; + + ec = (struct snd_soc_tplg_enum_control *)tplg->pos; + + /* validate kcontrol */ + if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) + return -EINVAL; + + se = devm_kzalloc(tplg->dev, sizeof(*se), GFP_KERNEL); + if (!se) + return -ENOMEM; + + tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + le32_to_cpu(ec->priv.size)); + + dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", ec->hdr.name, ec->items); + + kc->name = devm_kstrdup(tplg->dev, ec->hdr.name, GFP_KERNEL); + if (!kc->name) + return -ENOMEM; + kc->private_value = (long)se; + kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; + kc->access = le32_to_cpu(ec->hdr.access); + + /* we only support FL/FR channel mapping atm */ + se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); + se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); + se->shift_r = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR); + + se->mask = le32_to_cpu(ec->mask); + + switch (le32_to_cpu(ec->hdr.ops.info)) { + case SND_SOC_TPLG_CTL_ENUM_VALUE: + case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: + err = soc_tplg_denum_create_values(tplg, se, ec); + if (err < 0) { + dev_err(tplg->dev, "ASoC: could not create values for %s\n", ec->hdr.name); + return err; + } + fallthrough; + case SND_SOC_TPLG_CTL_ENUM: + case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: + case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: + err = soc_tplg_denum_create_texts(tplg, se, ec); + if (err < 0) { + dev_err(tplg->dev, "ASoC: could not create texts for %s\n", ec->hdr.name); + return err; + } + break; + default: + dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", + ec->hdr.ops.info, ec->hdr.name); + return -EINVAL; + } + + /* map io handlers */ + err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg); + if (err) { + soc_control_err(tplg, &ec->hdr, ec->hdr.name); + return err; + } + + /* pass control to driver for optional further init */ + return soc_tplg_control_load(tplg, kc, &ec->hdr); +} + +static int soc_tplg_control_dbytes_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) +{ + struct snd_soc_tplg_bytes_control *be; + struct soc_bytes_ext *sbe; + int err; + + be = (struct snd_soc_tplg_bytes_control *)tplg->pos; + + /* validate kcontrol */ + if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) + return -EINVAL; + + sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); + if (!sbe) + return -ENOMEM; + + tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + le32_to_cpu(be->priv.size)); + + dev_dbg(tplg->dev, "ASoC: adding bytes kcontrol %s with access 0x%x\n", + be->hdr.name, be->hdr.access); + + kc->name = devm_kstrdup(tplg->dev, be->hdr.name, GFP_KERNEL); + if (!kc->name) + return -ENOMEM; + kc->private_value = (long)sbe; + kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; + kc->access = le32_to_cpu(be->hdr.access); + + sbe->max = le32_to_cpu(be->max); + + /* map standard io handlers and check for external handlers */ + err = soc_tplg_kcontrol_bind_io(&be->hdr, kc, tplg); + if (err) { + soc_control_err(tplg, &be->hdr, be->hdr.name); + return err; + } + + /* pass control to driver for optional further init */ + return soc_tplg_control_load(tplg, kc, &be->hdr); +} + static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) { struct snd_soc_tplg_bytes_control *be; @@ -789,72 +1022,6 @@ err: return ret; } -static int soc_tplg_denum_create_texts(struct soc_tplg *tplg, struct soc_enum *se, - struct snd_soc_tplg_enum_control *ec) -{ - int i, ret; - - if (le32_to_cpu(ec->items) > ARRAY_SIZE(ec->texts)) - return -EINVAL; - - se->dobj.control.dtexts = - devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), sizeof(char *), GFP_KERNEL); - if (se->dobj.control.dtexts == NULL) - return -ENOMEM; - - for (i = 0; i < le32_to_cpu(ec->items); i++) { - - if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) { - ret = -EINVAL; - goto err; - } - - se->dobj.control.dtexts[i] = devm_kstrdup(tplg->dev, ec->texts[i], GFP_KERNEL); - if (!se->dobj.control.dtexts[i]) { - ret = -ENOMEM; - goto err; - } - } - - se->items = le32_to_cpu(ec->items); - se->texts = (const char * const *)se->dobj.control.dtexts; - return 0; - -err: - return ret; -} - -static int soc_tplg_denum_create_values(struct soc_tplg *tplg, struct soc_enum *se, - struct snd_soc_tplg_enum_control *ec) -{ - int i; - - /* - * Following "if" checks if we have at most SND_SOC_TPLG_NUM_TEXTS - * values instead of using ARRAY_SIZE(ec->values) due to the fact that - * it is oversized for its purpose. Additionally it is done so because - * it is defined in UAPI header where it can't be easily changed. - */ - if (le32_to_cpu(ec->items) > SND_SOC_TPLG_NUM_TEXTS) - return -EINVAL; - - se->dobj.control.dvalues = devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), - sizeof(*se->dobj.control.dvalues), - GFP_KERNEL); - if (!se->dobj.control.dvalues) - return -ENOMEM; - - /* convert from little-endian */ - for (i = 0; i < le32_to_cpu(ec->items); i++) { - se->dobj.control.dvalues[i] = le32_to_cpu(ec->values[i]); - } - - se->items = le32_to_cpu(ec->items); - se->values = (const unsigned int *)se->dobj.control.dvalues; - return 0; -} - static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size) { struct snd_soc_tplg_enum_control *ec; @@ -1096,173 +1263,6 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, return ret; } -static int soc_tplg_control_dmixer_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) -{ - struct snd_soc_tplg_mixer_control *mc; - struct soc_mixer_control *sm; - int err; - - mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; - - /* validate kcontrol */ - if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) - return -EINVAL; - - sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); - if (!sm) - return -ENOMEM; - - tplg->pos += sizeof(struct snd_soc_tplg_mixer_control) + le32_to_cpu(mc->priv.size); - - dev_dbg(tplg->dev, "ASoC: adding mixer kcontrol %s with access 0x%x\n", - mc->hdr.name, mc->hdr.access); - - kc->name = devm_kstrdup(tplg->dev, mc->hdr.name, GFP_KERNEL); - if (!kc->name) - return -ENOMEM; - kc->private_value = (long)sm; - kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; - kc->access = le32_to_cpu(mc->hdr.access); - - /* we only support FL/FR channel mapping atm */ - sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); - sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); - sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); - sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); - - sm->max = le32_to_cpu(mc->max); - sm->min = le32_to_cpu(mc->min); - sm->invert = le32_to_cpu(mc->invert); - sm->platform_max = le32_to_cpu(mc->platform_max); - - /* map io handlers */ - err = soc_tplg_kcontrol_bind_io(&mc->hdr, kc, tplg); - if (err) { - soc_control_err(tplg, &mc->hdr, mc->hdr.name); - return err; - } - - /* create any TLV data */ - err = soc_tplg_create_tlv(tplg, kc, &mc->hdr); - if (err < 0) { - dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); - return err; - } - - /* pass control to driver for optional further init */ - return soc_tplg_control_load(tplg, kc, &mc->hdr); -} - -static int soc_tplg_control_denum_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) -{ - struct snd_soc_tplg_enum_control *ec; - struct soc_enum *se; - int err; - - ec = (struct snd_soc_tplg_enum_control *)tplg->pos; - - /* validate kcontrol */ - if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) - return -EINVAL; - - se = devm_kzalloc(tplg->dev, sizeof(*se), GFP_KERNEL); - if (!se) - return -ENOMEM; - - tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + le32_to_cpu(ec->priv.size)); - - dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", ec->hdr.name, ec->items); - - kc->name = devm_kstrdup(tplg->dev, ec->hdr.name, GFP_KERNEL); - if (!kc->name) - return -ENOMEM; - kc->private_value = (long)se; - kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; - kc->access = le32_to_cpu(ec->hdr.access); - - /* we only support FL/FR channel mapping atm */ - se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); - se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); - se->shift_r = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR); - - se->mask = le32_to_cpu(ec->mask); - - switch (le32_to_cpu(ec->hdr.ops.info)) { - case SND_SOC_TPLG_CTL_ENUM_VALUE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: - err = soc_tplg_denum_create_values(tplg, se, ec); - if (err < 0) { - dev_err(tplg->dev, "ASoC: could not create values for %s\n", ec->hdr.name); - return err; - } - fallthrough; - case SND_SOC_TPLG_CTL_ENUM: - case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: - err = soc_tplg_denum_create_texts(tplg, se, ec); - if (err < 0) { - dev_err(tplg->dev, "ASoC: could not create texts for %s\n", ec->hdr.name); - return err; - } - break; - default: - dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", - ec->hdr.ops.info, ec->hdr.name); - return -EINVAL; - } - - /* map io handlers */ - err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg); - if (err) { - soc_control_err(tplg, &ec->hdr, ec->hdr.name); - return err; - } - - /* pass control to driver for optional further init */ - return soc_tplg_control_load(tplg, kc, &ec->hdr); -} - -static int soc_tplg_control_dbytes_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) -{ - struct snd_soc_tplg_bytes_control *be; - struct soc_bytes_ext *sbe; - int err; - - be = (struct snd_soc_tplg_bytes_control *)tplg->pos; - - /* validate kcontrol */ - if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) - return -EINVAL; - - sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); - if (!sbe) - return -ENOMEM; - - tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + le32_to_cpu(be->priv.size)); - - dev_dbg(tplg->dev, "ASoC: adding bytes kcontrol %s with access 0x%x\n", - be->hdr.name, be->hdr.access); - - kc->name = devm_kstrdup(tplg->dev, be->hdr.name, GFP_KERNEL); - if (!kc->name) - return -ENOMEM; - kc->private_value = (long)sbe; - kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; - kc->access = le32_to_cpu(be->hdr.access); - - sbe->max = le32_to_cpu(be->max); - - /* map standard io handlers and check for external handlers */ - err = soc_tplg_kcontrol_bind_io(&be->hdr, kc, tplg); - if (err) { - soc_control_err(tplg, &be->hdr, be->hdr.name); - return err; - } - - /* pass control to driver for optional further init */ - return soc_tplg_control_load(tplg, kc, &be->hdr); -} - static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, struct snd_soc_tplg_dapm_widget *w) { From 0867278200f787817036419fc87b56fb04a448e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:48 +0200 Subject: [PATCH 11/13] ASoC: topology: Unify code for creating standalone and widget bytes control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code used to create standalone and widget bytes control is same, with exception that in standalone case dynamic object needs to be registered and control created directly. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-12-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 51 +++++++--------------------------------- 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 5aab1df7e260..b10a6be8f75b 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -875,41 +875,21 @@ static int soc_tplg_control_dbytes_create(struct soc_tplg *tplg, struct snd_kcon static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) { - struct snd_soc_tplg_bytes_control *be; + struct snd_kcontrol_new kc = {0}; struct soc_bytes_ext *sbe; - struct snd_kcontrol_new kc; - int ret = 0; + int ret; if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_bytes_control), 1, size, "mixer bytes")) return -EINVAL; - be = (struct snd_soc_tplg_bytes_control *)tplg->pos; + ret = soc_tplg_control_dbytes_create(tplg, &kc); + if (ret) + return ret; - /* validate kcontrol */ - if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) - return -EINVAL; - - sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); - if (sbe == NULL) - return -ENOMEM; - - tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + - le32_to_cpu(be->priv.size)); - - dev_dbg(tplg->dev, - "ASoC: adding bytes kcontrol %s with access 0x%x\n", - be->hdr.name, be->hdr.access); - - memset(&kc, 0, sizeof(kc)); - kc.name = be->hdr.name; - kc.private_value = (long)sbe; - kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - kc.access = le32_to_cpu(be->hdr.access); - - sbe->max = le32_to_cpu(be->max); + /* register dynamic object */ + sbe = (struct soc_bytes_ext *)&kc.private_value; INIT_LIST_HEAD(&sbe->dobj.list); sbe->dobj.type = SND_SOC_DOBJ_BYTES; @@ -917,26 +897,13 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) if (tplg->ops) sbe->dobj.unload = tplg->ops->control_unload; - /* map io handlers */ - ret = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, tplg); - if (ret) { - soc_control_err(tplg, &be->hdr, be->hdr.name); - goto err; - } - - /* pass control to driver for optional further init */ - ret = soc_tplg_control_load(tplg, &kc, &be->hdr); - if (ret < 0) - goto err; - - /* register control here */ + /* create control directly */ ret = soc_tplg_add_kcontrol(tplg, &kc, &sbe->dobj.control.kcontrol); if (ret < 0) - goto err; + return ret; list_add(&sbe->dobj.list, &tplg->comp->dobj_list); -err: return ret; } From 4654ca7cc8d6b57c77436dd44b347cc7dd3f5f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:49 +0200 Subject: [PATCH 12/13] ASoC: topology: Unify code for creating standalone and widget mixer control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code used to create standalone and widget mixer control is same, with exception that in standalone case dynamic object needs to be registered and control created directly. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-13-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 66 ++++++---------------------------------- 1 file changed, 9 insertions(+), 57 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index b10a6be8f75b..5fde44808246 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -909,49 +909,21 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size) { - struct snd_soc_tplg_mixer_control *mc; + struct snd_kcontrol_new kc = {0}; struct soc_mixer_control *sm; - struct snd_kcontrol_new kc; - int ret = 0; + int ret; if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_mixer_control), 1, size, "mixers")) return -EINVAL; - mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; + ret = soc_tplg_control_dmixer_create(tplg, &kc); + if (ret) + return ret; - /* validate kcontrol */ - if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) - return -EINVAL; - - sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); - if (sm == NULL) - return -ENOMEM; - tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + - le32_to_cpu(mc->priv.size)); - - dev_dbg(tplg->dev, - "ASoC: adding mixer kcontrol %s with access 0x%x\n", - mc->hdr.name, mc->hdr.access); - - memset(&kc, 0, sizeof(kc)); - kc.name = mc->hdr.name; - kc.private_value = (long)sm; - kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - kc.access = le32_to_cpu(mc->hdr.access); - - /* we only support FL/FR channel mapping atm */ - sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); - sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); - sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); - sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); - - sm->max = le32_to_cpu(mc->max); - sm->min = le32_to_cpu(mc->min); - sm->invert = le32_to_cpu(mc->invert); - sm->platform_max = le32_to_cpu(mc->platform_max); + /* register dynamic object */ + sm = (struct soc_mixer_control *)&kc.private_value; INIT_LIST_HEAD(&sm->dobj.list); sm->dobj.type = SND_SOC_DOBJ_MIXER; @@ -959,33 +931,13 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size) if (tplg->ops) sm->dobj.unload = tplg->ops->control_unload; - /* map io handlers */ - ret = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, tplg); - if (ret) { - soc_control_err(tplg, &mc->hdr, mc->hdr.name); - goto err; - } - - /* create any TLV data */ - ret = soc_tplg_create_tlv(tplg, &kc, &mc->hdr); - if (ret < 0) { - dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); - goto err; - } - - /* pass control to driver for optional further init */ - ret = soc_tplg_control_load(tplg, &kc, &mc->hdr); - if (ret < 0) - goto err; - - /* register control here */ + /* create control directly */ ret = soc_tplg_add_kcontrol(tplg, &kc, &sm->dobj.control.kcontrol); if (ret < 0) - goto err; + return ret; list_add(&sm->dobj.list, &tplg->comp->dobj_list); -err: return ret; } From 8f2942b9198c935862bc2400602780844b352667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Thu, 27 Jun 2024 12:18:50 +0200 Subject: [PATCH 13/13] ASoC: topology: Unify code for creating standalone and widget enum control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code used to create standalone and widget enum control is same, with exception that in standalone case dynamic object needs to be registered and control created directly. Signed-off-by: Amadeusz Sławiński Link: https://patch.msgid.link/20240627101850.2191513-14-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 86 +++++----------------------------------- 1 file changed, 9 insertions(+), 77 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 5fde44808246..af5d42b57be7 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -943,46 +943,21 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size) static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size) { - struct snd_soc_tplg_enum_control *ec; + struct snd_kcontrol_new kc = {0}; struct soc_enum *se; - struct snd_kcontrol_new kc; - int ret = 0; + int ret; if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_enum_control), 1, size, "enums")) return -EINVAL; - ec = (struct snd_soc_tplg_enum_control *)tplg->pos; + ret = soc_tplg_control_denum_create(tplg, &kc); + if (ret) + return ret; - /* validate kcontrol */ - if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) - return -EINVAL; - - se = devm_kzalloc(tplg->dev, (sizeof(*se)), GFP_KERNEL); - if (se == NULL) - return -ENOMEM; - - tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + - le32_to_cpu(ec->priv.size)); - - dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", - ec->hdr.name, ec->items); - - memset(&kc, 0, sizeof(kc)); - kc.name = ec->hdr.name; - kc.private_value = (long)se; - kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - kc.access = le32_to_cpu(ec->hdr.access); - - se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); - se->shift_l = tplg_chan_get_shift(tplg, ec->channel, - SNDRV_CHMAP_FL); - se->shift_r = tplg_chan_get_shift(tplg, ec->channel, - SNDRV_CHMAP_FR); - - se->mask = le32_to_cpu(ec->mask); + /* register dynamic object */ + se = (struct soc_enum *)kc.private_value; INIT_LIST_HEAD(&se->dobj.list); se->dobj.type = SND_SOC_DOBJ_ENUM; @@ -990,56 +965,13 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size) if (tplg->ops) se->dobj.unload = tplg->ops->control_unload; - switch (le32_to_cpu(ec->hdr.ops.info)) { - case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: - case SND_SOC_TPLG_CTL_ENUM_VALUE: - ret = soc_tplg_denum_create_values(tplg, se, ec); - if (ret < 0) { - dev_err(tplg->dev, - "ASoC: could not create values for %s\n", - ec->hdr.name); - goto err; - } - fallthrough; - case SND_SOC_TPLG_CTL_ENUM: - case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: - ret = soc_tplg_denum_create_texts(tplg, se, ec); - if (ret < 0) { - dev_err(tplg->dev, - "ASoC: could not create texts for %s\n", - ec->hdr.name); - goto err; - } - break; - default: - ret = -EINVAL; - dev_err(tplg->dev, - "ASoC: invalid enum control type %d for %s\n", - ec->hdr.ops.info, ec->hdr.name); - goto err; - } - - /* map io handlers */ - ret = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg); - if (ret) { - soc_control_err(tplg, &ec->hdr, ec->hdr.name); - goto err; - } - - /* pass control to driver for optional further init */ - ret = soc_tplg_control_load(tplg, &kc, &ec->hdr); - if (ret < 0) - goto err; - - /* register control here */ + /* create control directly */ ret = soc_tplg_add_kcontrol(tplg, &kc, &se->dobj.control.kcontrol); if (ret < 0) - goto err; + return ret; list_add(&se->dobj.list, &tplg->comp->dobj_list); -err: return ret; }