Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: Intel: avs: Parse control tuples

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>

authored by

Amadeusz Sławiński
Cezary Rojewski
and committed by
Mark Brown
be2b81b5 585b9427

+93
+4
include/uapi/sound/intel/avs/tokens.h
··· 108 108 AVS_TKN_MOD_CORE_ID_U8 = 1704, 109 109 AVS_TKN_MOD_PROC_DOMAIN_U8 = 1705, 110 110 AVS_TKN_MOD_MODCFG_EXT_ID_U32 = 1706, 111 + AVS_TKN_MOD_KCONTROL_ID_U32 = 1707, 111 112 112 113 /* struct avs_tplg_path_template */ 113 114 AVS_TKN_PATH_TMPL_ID_U32 = 1801, ··· 122 121 AVS_TKN_PIN_FMT_INDEX_U32 = 2201, 123 122 AVS_TKN_PIN_FMT_IOBS_U32 = 2202, 124 123 AVS_TKN_PIN_FMT_AFMT_ID_U32 = 2203, 124 + 125 + /* struct avs_tplg_kcontrol */ 126 + AVS_TKN_KCONTROL_ID_U32 = 2301, 125 127 }; 126 128 127 129 #endif
+10
sound/soc/intel/avs/control.c
··· 23 23 24 24 static struct avs_path_module *avs_get_kcontrol_module(struct avs_dev *adev, u32 id) 25 25 { 26 + struct avs_path *path; 27 + struct avs_path_pipeline *ppl; 28 + struct avs_path_module *mod; 29 + 30 + list_for_each_entry(path, &adev->path_list, node) 31 + list_for_each_entry(ppl, &path->ppl_list, node) 32 + list_for_each_entry(mod, &ppl->mod_list, node) 33 + if (mod->template->ctl_id && mod->template->ctl_id == id) 34 + return mod; 35 + 26 36 return NULL; 27 37 } 28 38
+76
sound/soc/intel/avs/topology.c
··· 13 13 #include <sound/soc-topology.h> 14 14 #include <uapi/sound/intel/avs/tokens.h> 15 15 #include "avs.h" 16 + #include "control.h" 16 17 #include "topology.h" 17 18 18 19 /* Get pointer to vendor array at the specified offset. */ ··· 1071 1070 .offset = offsetof(struct avs_tplg_module, cfg_ext), 1072 1071 .parse = avs_parse_modcfg_ext_ptr, 1073 1072 }, 1073 + { 1074 + .token = AVS_TKN_MOD_KCONTROL_ID_U32, 1075 + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1076 + .offset = offsetof(struct avs_tplg_module, ctl_id), 1077 + .parse = avs_parse_byte_token, 1078 + }, 1074 1079 }; 1075 1080 1076 1081 static struct avs_tplg_module * ··· 1442 1435 return 0; 1443 1436 } 1444 1437 1438 + static int avs_widget_ready(struct snd_soc_component *comp, int index, 1439 + struct snd_soc_dapm_widget *w, 1440 + struct snd_soc_tplg_dapm_widget *dw) 1441 + { 1442 + struct avs_tplg_path_template *template = w->priv; 1443 + 1444 + template->w = w; 1445 + return 0; 1446 + } 1447 + 1445 1448 static int avs_dai_load(struct snd_soc_component *comp, int index, 1446 1449 struct snd_soc_dai_driver *dai_drv, struct snd_soc_tplg_pcm *pcm, 1447 1450 struct snd_soc_dai *dai) ··· 1603 1586 return avs_tplg_parse_bindings(comp, tuples, remaining); 1604 1587 } 1605 1588 1589 + #define AVS_CONTROL_OPS_VOLUME 257 1590 + 1591 + static const struct snd_soc_tplg_kcontrol_ops avs_control_ops[] = { 1592 + { 1593 + .id = AVS_CONTROL_OPS_VOLUME, 1594 + .get = avs_control_volume_get, 1595 + .put = avs_control_volume_put, 1596 + }, 1597 + }; 1598 + 1599 + static const struct avs_tplg_token_parser control_parsers[] = { 1600 + { 1601 + .token = AVS_TKN_KCONTROL_ID_U32, 1602 + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1603 + .offset = offsetof(struct avs_control_data, id), 1604 + .parse = avs_parse_word_token, 1605 + }, 1606 + }; 1607 + 1608 + static int 1609 + avs_control_load(struct snd_soc_component *comp, int index, struct snd_kcontrol_new *ctmpl, 1610 + struct snd_soc_tplg_ctl_hdr *hdr) 1611 + { 1612 + struct snd_soc_tplg_vendor_array *tuples; 1613 + struct snd_soc_tplg_mixer_control *tmc; 1614 + struct avs_control_data *ctl_data; 1615 + struct soc_mixer_control *mc; 1616 + size_t block_size; 1617 + int ret; 1618 + 1619 + switch (hdr->type) { 1620 + case SND_SOC_TPLG_TYPE_MIXER: 1621 + tmc = container_of(hdr, typeof(*tmc), hdr); 1622 + tuples = tmc->priv.array; 1623 + block_size = le32_to_cpu(tmc->priv.size); 1624 + break; 1625 + default: 1626 + return -EINVAL; 1627 + } 1628 + 1629 + ctl_data = devm_kzalloc(comp->card->dev, sizeof(*ctl_data), GFP_KERNEL); 1630 + if (!ctl_data) 1631 + return -ENOMEM; 1632 + 1633 + ret = parse_dictionary_entries(comp, tuples, block_size, ctl_data, 1, sizeof(*ctl_data), 1634 + AVS_TKN_KCONTROL_ID_U32, control_parsers, 1635 + ARRAY_SIZE(control_parsers)); 1636 + if (ret) 1637 + return ret; 1638 + 1639 + mc = (struct soc_mixer_control *)ctmpl->private_value; 1640 + mc->dobj.private = ctl_data; 1641 + return 0; 1642 + } 1643 + 1606 1644 static struct snd_soc_tplg_ops avs_tplg_ops = { 1645 + .io_ops = avs_control_ops, 1646 + .io_ops_count = ARRAY_SIZE(avs_control_ops), 1647 + .control_load = avs_control_load, 1607 1648 .dapm_route_load = avs_route_load, 1608 1649 .widget_load = avs_widget_load, 1650 + .widget_ready = avs_widget_ready, 1609 1651 .dai_load = avs_dai_load, 1610 1652 .link_load = avs_link_load, 1611 1653 .manifest = avs_manifest,
+3
sound/soc/intel/avs/topology.h
··· 138 138 struct avs_tplg_path_template { 139 139 u32 id; 140 140 141 + struct snd_soc_dapm_widget *w; 142 + 141 143 struct list_head path_list; 142 144 143 145 struct avs_tplg *owner; ··· 182 180 u8 core_id; 183 181 u8 domain; 184 182 struct avs_tplg_modcfg_ext *cfg_ext; 183 + u32 ctl_id; 185 184 186 185 struct avs_tplg_pipeline *owner; 187 186 /* Pipeline modules management. */