ASoC: Intel: avs: Parse control tuples
authorAmadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Wed, 14 Dec 2022 18:54:59 +0000 (19:54 +0100)
committerMark Brown <broonie@kernel.org>
Sun, 25 Dec 2022 23:33:03 +0000 (23:33 +0000)
Add callback to handle loading of kcontrol and linking it to active
widget. In order to link kcontrol to specific modules add additional
field to module data, as well as specify control id in kcontrol data.

Co-authored-by: Cezary Rojewski <cezary.rojewski@intel.com>
Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Link: https://lore.kernel.org/r/20221214185500.3896902-4-amadeuszx.slawinski@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/uapi/sound/intel/avs/tokens.h
sound/soc/intel/avs/control.c
sound/soc/intel/avs/topology.c
sound/soc/intel/avs/topology.h

index 754f02b2f4440d26c08ece1f1ba2f8c72719cba7..4ffe546aa409a19f67c123fc7bb1a3ec577ab2de 100644 (file)
@@ -108,6 +108,7 @@ enum avs_tplg_token {
        AVS_TKN_MOD_CORE_ID_U8                          = 1704,
        AVS_TKN_MOD_PROC_DOMAIN_U8                      = 1705,
        AVS_TKN_MOD_MODCFG_EXT_ID_U32                   = 1706,
+       AVS_TKN_MOD_KCONTROL_ID_U32                     = 1707,
 
        /* struct avs_tplg_path_template */
        AVS_TKN_PATH_TMPL_ID_U32                        = 1801,
@@ -121,6 +122,9 @@ enum avs_tplg_token {
        AVS_TKN_PIN_FMT_INDEX_U32                       = 2201,
        AVS_TKN_PIN_FMT_IOBS_U32                        = 2202,
        AVS_TKN_PIN_FMT_AFMT_ID_U32                     = 2203,
+
+       /* struct avs_tplg_kcontrol */
+       AVS_TKN_KCONTROL_ID_U32                         = 2301,
 };
 
 #endif
index 92b3aad0bacaed8edeeef147ced049c712f11637..a8b14b784f8a519c61af84b87b54685be60d66f1 100644 (file)
@@ -23,6 +23,16 @@ static struct avs_dev *avs_get_kcontrol_adev(struct snd_kcontrol *kcontrol)
 
 static struct avs_path_module *avs_get_kcontrol_module(struct avs_dev *adev, u32 id)
 {
+       struct avs_path *path;
+       struct avs_path_pipeline *ppl;
+       struct avs_path_module *mod;
+
+       list_for_each_entry(path, &adev->path_list, node)
+               list_for_each_entry(ppl, &path->ppl_list, node)
+                       list_for_each_entry(mod, &ppl->mod_list, node)
+                               if (mod->template->ctl_id && mod->template->ctl_id == id)
+                                       return mod;
+
        return NULL;
 }
 
index e845eaf0a1e77d400e0534e1f06a89fcce10ad51..5fee7a8ec06ac107e66b46289092e7ad47a72b00 100644 (file)
@@ -13,6 +13,7 @@
 #include <sound/soc-topology.h>
 #include <uapi/sound/intel/avs/tokens.h>
 #include "avs.h"
+#include "control.h"
 #include "topology.h"
 
 /* Get pointer to vendor array at the specified offset. */
@@ -1070,6 +1071,12 @@ static const struct avs_tplg_token_parser module_parsers[] = {
                .offset = offsetof(struct avs_tplg_module, cfg_ext),
                .parse = avs_parse_modcfg_ext_ptr,
        },
+       {
+               .token = AVS_TKN_MOD_KCONTROL_ID_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_module, ctl_id),
+               .parse = avs_parse_byte_token,
+       },
 };
 
 static struct avs_tplg_module *
@@ -1435,6 +1442,16 @@ static int avs_widget_load(struct snd_soc_component *comp, int index,
        return 0;
 }
 
+static int avs_widget_ready(struct snd_soc_component *comp, int index,
+                           struct snd_soc_dapm_widget *w,
+                           struct snd_soc_tplg_dapm_widget *dw)
+{
+       struct avs_tplg_path_template *template = w->priv;
+
+       template->w = w;
+       return 0;
+}
+
 static int avs_dai_load(struct snd_soc_component *comp, int index,
                        struct snd_soc_dai_driver *dai_drv, struct snd_soc_tplg_pcm *pcm,
                        struct snd_soc_dai *dai)
@@ -1586,9 +1603,68 @@ static int avs_manifest(struct snd_soc_component *comp, int index,
        return avs_tplg_parse_bindings(comp, tuples, remaining);
 }
 
+#define AVS_CONTROL_OPS_VOLUME 257
+
+static const struct snd_soc_tplg_kcontrol_ops avs_control_ops[] = {
+       {
+               .id = AVS_CONTROL_OPS_VOLUME,
+               .get = avs_control_volume_get,
+               .put = avs_control_volume_put,
+       },
+};
+
+static const struct avs_tplg_token_parser control_parsers[] = {
+       {
+               .token = AVS_TKN_KCONTROL_ID_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_control_data, id),
+               .parse = avs_parse_word_token,
+       },
+};
+
+static int
+avs_control_load(struct snd_soc_component *comp, int index, struct snd_kcontrol_new *ctmpl,
+                struct snd_soc_tplg_ctl_hdr *hdr)
+{
+       struct snd_soc_tplg_vendor_array *tuples;
+       struct snd_soc_tplg_mixer_control *tmc;
+       struct avs_control_data *ctl_data;
+       struct soc_mixer_control *mc;
+       size_t block_size;
+       int ret;
+
+       switch (hdr->type) {
+       case SND_SOC_TPLG_TYPE_MIXER:
+               tmc = container_of(hdr, typeof(*tmc), hdr);
+               tuples = tmc->priv.array;
+               block_size = le32_to_cpu(tmc->priv.size);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ctl_data = devm_kzalloc(comp->card->dev, sizeof(*ctl_data), GFP_KERNEL);
+       if (!ctl_data)
+               return -ENOMEM;
+
+       ret = parse_dictionary_entries(comp, tuples, block_size, ctl_data, 1, sizeof(*ctl_data),
+                                      AVS_TKN_KCONTROL_ID_U32, control_parsers,
+                                      ARRAY_SIZE(control_parsers));
+       if (ret)
+               return ret;
+
+       mc = (struct soc_mixer_control *)ctmpl->private_value;
+       mc->dobj.private = ctl_data;
+       return 0;
+}
+
 static struct snd_soc_tplg_ops avs_tplg_ops = {
+       .io_ops                 = avs_control_ops,
+       .io_ops_count           = ARRAY_SIZE(avs_control_ops),
+       .control_load           = avs_control_load,
        .dapm_route_load        = avs_route_load,
        .widget_load            = avs_widget_load,
+       .widget_ready           = avs_widget_ready,
        .dai_load               = avs_dai_load,
        .link_load              = avs_link_load,
        .manifest               = avs_manifest,
index 68e5f6312353d2cad9e3a8cbf1ac18519747bb3d..6e1c8e9b24964117a43ffb45072777fd2fa8e3a5 100644 (file)
@@ -138,6 +138,8 @@ struct avs_tplg_path_template_id {
 struct avs_tplg_path_template {
        u32 id;
 
+       struct snd_soc_dapm_widget *w;
+
        struct list_head path_list;
 
        struct avs_tplg *owner;
@@ -180,6 +182,7 @@ struct avs_tplg_module {
        u8 core_id;
        u8 domain;
        struct avs_tplg_modcfg_ext *cfg_ext;
+       u32 ctl_id;
 
        struct avs_tplg_pipeline *owner;
        /* Pipeline modules management. */