ASoC: Intel: avs: Parse module-extension tuples
authorCezary Rojewski <cezary.rojewski@intel.com>
Thu, 31 Mar 2022 13:52:35 +0000 (15:52 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 19 Apr 2022 11:03:52 +0000 (12:03 +0100)
Anything that goes beyond module base config is an extension config. It
covers all fields for all specific module types available in ADSP
firmware. Add parsing helpers to support loading such information from
the topology file.

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

index 4ac44cb318f7e34b03450f0db02eed9259497783..d13e27dd655e2939a82e33344bf5e45b657ae846 100644 (file)
@@ -344,6 +344,7 @@ avs_parse_##name##_ptr(struct snd_soc_component *comp, void *elem, void *object,
 
 AVS_DEFINE_PTR_PARSER(audio_format, struct avs_audio_format, fmts);
 AVS_DEFINE_PTR_PARSER(modcfg_base, struct avs_tplg_modcfg_base, modcfgs_base);
+AVS_DEFINE_PTR_PARSER(modcfg_ext, struct avs_tplg_modcfg_ext, modcfgs_ext);
 
 static int
 parse_audio_format_bitfield(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
@@ -593,3 +594,299 @@ static int avs_tplg_parse_modcfgs_base(struct snd_soc_component *comp,
                                AVS_TKN_MODCFG_BASE_ID_U32,
                                modcfg_base_parsers, ARRAY_SIZE(modcfg_base_parsers));
 }
+
+static const struct avs_tplg_token_parser modcfg_ext_parsers[] = {
+       {
+               .token = AVS_TKN_MODCFG_EXT_TYPE_UUID,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_UUID,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, type),
+               .parse = avs_parse_uuid_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_CPR_OUT_AFMT_ID_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, copier.out_fmt),
+               .parse = avs_parse_audio_format_ptr,
+       },
+       {
+               .token = AVS_TKN_MODCFG_CPR_FEATURE_MASK_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, copier.feature_mask),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_CPR_VINDEX_U8,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, copier.vindex),
+               .parse = avs_parse_byte_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_CPR_DMA_TYPE_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, copier.dma_type),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_CPR_DMABUFF_SIZE_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, copier.dma_buffer_size),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_CPR_BLOB_FMT_ID_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, copier.blob_fmt),
+               .parse = avs_parse_audio_format_ptr,
+       },
+       {
+               .token = AVS_TKN_MODCFG_MICSEL_OUT_AFMT_ID_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, micsel.out_fmt),
+               .parse = avs_parse_audio_format_ptr,
+       },
+       {
+               .token = AVS_TKN_MODCFG_INTELWOV_CPC_LP_MODE_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, wov.cpc_lp_mode),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_SRC_OUT_FREQ_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, src.out_freq),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_MUX_REF_AFMT_ID_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, mux.ref_fmt),
+               .parse = avs_parse_audio_format_ptr,
+       },
+       {
+               .token = AVS_TKN_MODCFG_MUX_OUT_AFMT_ID_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, mux.out_fmt),
+               .parse = avs_parse_audio_format_ptr,
+       },
+       {
+               .token = AVS_TKN_MODCFG_AEC_REF_AFMT_ID_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, aec.ref_fmt),
+               .parse = avs_parse_audio_format_ptr,
+       },
+       {
+               .token = AVS_TKN_MODCFG_AEC_OUT_AFMT_ID_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, aec.out_fmt),
+               .parse = avs_parse_audio_format_ptr,
+       },
+       {
+               .token = AVS_TKN_MODCFG_AEC_CPC_LP_MODE_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, aec.cpc_lp_mode),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_ASRC_OUT_FREQ_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.out_freq),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_ASRC_MODE_U8,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.mode),
+               .parse = avs_parse_byte_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_ASRC_DISABLE_JITTER_U8,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.disable_jitter_buffer),
+               .parse = avs_parse_byte_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_OUT_CHAN_CFG_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.out_channel_config),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_SELECT_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients_select),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_0_S32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[0]),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_1_S32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[1]),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_2_S32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[2]),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_3_S32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[3]),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_4_S32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[4]),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_5_S32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[5]),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_6_S32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[6]),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_7_S32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[7]),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_UPDOWN_MIX_CHAN_MAP_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.channel_map),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_EXT_NUM_INPUT_PINS_U16,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_input_pins),
+               .parse = avs_parse_short_token,
+       },
+       {
+               .token = AVS_TKN_MODCFG_EXT_NUM_OUTPUT_PINS_U16,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
+               .offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_output_pins),
+               .parse = avs_parse_short_token,
+       },
+};
+
+static const struct avs_tplg_token_parser pin_format_parsers[] = {
+       {
+               .token = AVS_TKN_PIN_FMT_INDEX_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_pin_format, pin_index),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_PIN_FMT_IOBS_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_pin_format, iobs),
+               .parse = avs_parse_word_token,
+       },
+       {
+               .token = AVS_TKN_PIN_FMT_AFMT_ID_U32,
+               .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+               .offset = offsetof(struct avs_tplg_pin_format, fmt),
+               .parse = avs_parse_audio_format_ptr,
+       },
+};
+
+static int avs_tplg_parse_modcfg_ext(struct snd_soc_component *comp,
+                                    struct avs_tplg_modcfg_ext *cfg,
+                                    struct snd_soc_tplg_vendor_array *tuples,
+                                    u32 block_size)
+{
+       u32 esize;
+       int ret;
+
+       /* See where pin block starts. */
+       ret = avs_tplg_vendor_entry_size(tuples, block_size,
+                                        AVS_TKN_PIN_FMT_INDEX_U32, &esize);
+       if (ret)
+               return ret;
+
+       ret = avs_parse_tokens(comp, cfg, modcfg_ext_parsers,
+                              ARRAY_SIZE(modcfg_ext_parsers), tuples, esize);
+       if (ret)
+               return ret;
+
+       block_size -= esize;
+       /* Parse trailing in/out pin formats if any. */
+       if (block_size) {
+               struct avs_tplg_pin_format *pins;
+               u32 num_pins;
+
+               num_pins = cfg->generic.num_input_pins + cfg->generic.num_output_pins;
+               if (!num_pins)
+                       return -EINVAL;
+
+               pins = devm_kcalloc(comp->card->dev, num_pins, sizeof(*pins), GFP_KERNEL);
+               if (!pins)
+                       return -ENOMEM;
+
+               tuples = avs_tplg_vendor_array_at(tuples, esize);
+               ret = parse_dictionary_entries(comp, tuples, block_size,
+                                              pins, num_pins, sizeof(*pins),
+                                              AVS_TKN_PIN_FMT_INDEX_U32,
+                                              pin_format_parsers,
+                                              ARRAY_SIZE(pin_format_parsers));
+               if (ret)
+                       return ret;
+               cfg->generic.pin_fmts = pins;
+       }
+
+       return 0;
+}
+
+static int avs_tplg_parse_modcfgs_ext(struct snd_soc_component *comp,
+                                     struct snd_soc_tplg_vendor_array *tuples,
+                                     u32 block_size)
+{
+       struct avs_soc_component *acomp = to_avs_soc_component(comp);
+       struct avs_tplg *tplg = acomp->tplg;
+       int ret, i;
+
+       ret = parse_dictionary_header(comp, tuples, (void **)&tplg->modcfgs_ext,
+                                     &tplg->num_modcfgs_ext,
+                                     sizeof(*tplg->modcfgs_ext),
+                                     AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32);
+       if (ret)
+               return ret;
+
+       block_size -= le32_to_cpu(tuples->size);
+       /* With header parsed, move on to parsing entries. */
+       tuples = avs_tplg_vendor_array_next(tuples);
+
+       for (i = 0; i < tplg->num_modcfgs_ext; i++) {
+               struct avs_tplg_modcfg_ext *cfg = &tplg->modcfgs_ext[i];
+               u32 esize;
+
+               ret = avs_tplg_vendor_entry_size(tuples, block_size,
+                                                AVS_TKN_MODCFG_EXT_ID_U32, &esize);
+               if (ret)
+                       return ret;
+
+               ret = avs_tplg_parse_modcfg_ext(comp, cfg, tuples, esize);
+               if (ret)
+                       return ret;
+
+               block_size -= esize;
+               tuples = avs_tplg_vendor_array_at(tuples, esize);
+       }
+
+       return 0;
+}
index a3ab5d15c9ee708e6bbdd476bb279e1a9da488cc..ce51fd7a99de38a138f2220dc0f22b1ae1aac918 100644 (file)
@@ -27,6 +27,8 @@ struct avs_tplg {
        u32 num_fmts;
        struct avs_tplg_modcfg_base *modcfgs_base;
        u32 num_modcfgs_base;
+       struct avs_tplg_modcfg_ext *modcfgs_ext;
+       u32 num_modcfgs_ext;
 };
 
 struct avs_tplg_library {
@@ -41,4 +43,61 @@ struct avs_tplg_modcfg_base {
        u32 is_pages;
 };
 
+struct avs_tplg_pin_format {
+       u32 pin_index;
+       u32 iobs;
+       struct avs_audio_format *fmt;
+};
+
+struct avs_tplg_modcfg_ext {
+       guid_t type;
+
+       union {
+               struct {
+                       u16 num_input_pins;
+                       u16 num_output_pins;
+                       struct avs_tplg_pin_format *pin_fmts;
+               } generic;
+               struct {
+                       struct avs_audio_format *out_fmt;
+                       struct avs_audio_format *blob_fmt; /* optional override */
+                       u32 feature_mask;
+                       union avs_virtual_index vindex;
+                       u32 dma_type;
+                       u32 dma_buffer_size;
+                       u32 config_length;
+                       /* config_data part of priv data */
+               } copier;
+               struct {
+                       u32 out_channel_config;
+                       u32 coefficients_select;
+                       s32 coefficients[AVS_CHANNELS_MAX];
+                       u32 channel_map;
+               } updown_mix;
+               struct {
+                       u32 out_freq;
+               } src;
+               struct {
+                       u32 out_freq;
+                       u8 mode;
+                       u8 disable_jitter_buffer;
+               } asrc;
+               struct {
+                       u32 cpc_lp_mode;
+               } wov;
+               struct {
+                       struct avs_audio_format *ref_fmt;
+                       struct avs_audio_format *out_fmt;
+                       u32 cpc_lp_mode;
+               } aec;
+               struct {
+                       struct avs_audio_format *ref_fmt;
+                       struct avs_audio_format *out_fmt;
+               } mux;
+               struct {
+                       struct avs_audio_format *out_fmt;
+               } micsel;
+       };
+};
+
 #endif