Commit 9e85ec40 authored by Cezary Rojewski's avatar Cezary Rojewski Committed by Mark Brown

ASoC: Intel: avs: Parse module-extension tuples

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: default avatarAmadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Signed-off-by: default avatarCezary Rojewski <cezary.rojewski@intel.com>
Link: https://lore.kernel.org/r/20220331135246.993089-4-cezary.rojewski@intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 34ae2cd5
......@@ -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;
}
......@@ -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
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