Skip to content

Commit f2cf24a

Browse files
ranj063broonie
authored andcommitted
ASoC: SOF: topology: Make effect widget parsing IPC agnostic
Define the list of tokens pertaining to effect type widgets, parse and save them as part of the swidget tuples array. Once topology parsing is complete, these tokens will be applied to create the IPC structure for the process component based on the topology widget_setup op in ipc3_tplg_ops. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20220314200520.1233427-15-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 111d66f commit f2cf24a

File tree

2 files changed

+257
-268
lines changed

2 files changed

+257
-268
lines changed

sound/soc/sof/ipc3-topology.c

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,51 @@
1313
#include "sof-audio.h"
1414
#include "ops.h"
1515

16+
struct sof_widget_data {
17+
int ctrl_type;
18+
int ipc_cmd;
19+
struct sof_abi_hdr *pdata;
20+
struct snd_sof_control *control;
21+
};
22+
23+
struct sof_process_types {
24+
const char *name;
25+
enum sof_ipc_process_type type;
26+
enum sof_comp_type comp_type;
27+
};
28+
29+
static const struct sof_process_types sof_process[] = {
30+
{"EQFIR", SOF_PROCESS_EQFIR, SOF_COMP_EQ_FIR},
31+
{"EQIIR", SOF_PROCESS_EQIIR, SOF_COMP_EQ_IIR},
32+
{"KEYWORD_DETECT", SOF_PROCESS_KEYWORD_DETECT, SOF_COMP_KEYWORD_DETECT},
33+
{"KPB", SOF_PROCESS_KPB, SOF_COMP_KPB},
34+
{"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR},
35+
{"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX},
36+
{"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX},
37+
{"DCBLOCK", SOF_PROCESS_DCBLOCK, SOF_COMP_DCBLOCK},
38+
{"SMART_AMP", SOF_PROCESS_SMART_AMP, SOF_COMP_SMART_AMP},
39+
};
40+
41+
static enum sof_ipc_process_type find_process(const char *name)
42+
{
43+
int i;
44+
45+
for (i = 0; i < ARRAY_SIZE(sof_process); i++) {
46+
if (strcmp(name, sof_process[i].name) == 0)
47+
return sof_process[i].type;
48+
}
49+
50+
return SOF_PROCESS_NONE;
51+
}
52+
53+
static int get_token_process_type(void *elem, void *object, u32 offset)
54+
{
55+
u32 *val = (u32 *)((u8 *)object + offset);
56+
57+
*val = find_process((const char *)elem);
58+
return 0;
59+
}
60+
1661
/* Buffers */
1762
static const struct sof_topology_token buffer_tokens[] = {
1863
{SOF_TKN_BUF_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
@@ -71,6 +116,12 @@ static const struct sof_topology_token asrc_tokens[] = {
71116
offsetof(struct sof_ipc_comp_asrc, operation_mode)},
72117
};
73118

119+
/* EFFECT */
120+
static const struct sof_topology_token process_tokens[] = {
121+
{SOF_TKN_PROCESS_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_process_type,
122+
offsetof(struct sof_ipc_comp_process, type)},
123+
};
124+
74125
/* PCM */
75126
static const struct sof_topology_token pcm_tokens[] = {
76127
{SOF_TKN_PCM_DMAC_CONFIG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
@@ -111,6 +162,7 @@ static const struct sof_token_info ipc3_token_list[SOF_TOKEN_COUNT] = {
111162
[SOF_VOLUME_TOKENS] = {"Volume tokens", volume_tokens, ARRAY_SIZE(volume_tokens)},
112163
[SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)},
113164
[SOF_ASRC_TOKENS] = {"ASRC tokens", asrc_tokens, ARRAY_SIZE(asrc_tokens)},
165+
[SOF_PROCESS_TOKENS] = {"Process tokens", process_tokens, ARRAY_SIZE(process_tokens)},
114166
};
115167

116168
/**
@@ -558,6 +610,193 @@ static int sof_ipc3_widget_setup_comp_pga(struct snd_sof_widget *swidget)
558610
return ret;
559611
}
560612

613+
static int sof_get_control_data(struct snd_soc_component *scomp,
614+
struct snd_soc_dapm_widget *widget,
615+
struct sof_widget_data *wdata, size_t *size)
616+
{
617+
const struct snd_kcontrol_new *kc;
618+
struct soc_mixer_control *sm;
619+
struct soc_bytes_ext *sbe;
620+
struct soc_enum *se;
621+
int i;
622+
623+
*size = 0;
624+
625+
for (i = 0; i < widget->num_kcontrols; i++) {
626+
kc = &widget->kcontrol_news[i];
627+
628+
switch (widget->dobj.widget.kcontrol_type[i]) {
629+
case SND_SOC_TPLG_TYPE_MIXER:
630+
sm = (struct soc_mixer_control *)kc->private_value;
631+
wdata[i].control = sm->dobj.private;
632+
break;
633+
case SND_SOC_TPLG_TYPE_BYTES:
634+
sbe = (struct soc_bytes_ext *)kc->private_value;
635+
wdata[i].control = sbe->dobj.private;
636+
break;
637+
case SND_SOC_TPLG_TYPE_ENUM:
638+
se = (struct soc_enum *)kc->private_value;
639+
wdata[i].control = se->dobj.private;
640+
break;
641+
default:
642+
dev_err(scomp->dev, "Unknown kcontrol type %u in widget %s\n",
643+
widget->dobj.widget.kcontrol_type[i], widget->name);
644+
return -EINVAL;
645+
}
646+
647+
if (!wdata[i].control) {
648+
dev_err(scomp->dev, "No scontrol for widget %s\n", widget->name);
649+
return -EINVAL;
650+
}
651+
652+
wdata[i].pdata = wdata[i].control->control_data->data;
653+
if (!wdata[i].pdata)
654+
return -EINVAL;
655+
656+
/* make sure data is valid - data can be updated at runtime */
657+
if (widget->dobj.widget.kcontrol_type[i] == SND_SOC_TPLG_TYPE_BYTES &&
658+
wdata[i].pdata->magic != SOF_ABI_MAGIC)
659+
return -EINVAL;
660+
661+
*size += wdata[i].pdata->size;
662+
663+
/* get data type */
664+
switch (wdata[i].control->control_data->cmd) {
665+
case SOF_CTRL_CMD_VOLUME:
666+
case SOF_CTRL_CMD_ENUM:
667+
case SOF_CTRL_CMD_SWITCH:
668+
wdata[i].ipc_cmd = SOF_IPC_COMP_SET_VALUE;
669+
wdata[i].ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET;
670+
break;
671+
case SOF_CTRL_CMD_BINARY:
672+
wdata[i].ipc_cmd = SOF_IPC_COMP_SET_DATA;
673+
wdata[i].ctrl_type = SOF_CTRL_TYPE_DATA_SET;
674+
break;
675+
default:
676+
break;
677+
}
678+
}
679+
680+
return 0;
681+
}
682+
683+
static int sof_process_load(struct snd_soc_component *scomp,
684+
struct snd_sof_widget *swidget, int type)
685+
{
686+
struct snd_soc_dapm_widget *widget = swidget->widget;
687+
struct sof_ipc_comp_process *process;
688+
struct sof_widget_data *wdata = NULL;
689+
size_t ipc_data_size = 0;
690+
size_t ipc_size;
691+
int offset = 0;
692+
int ret;
693+
int i;
694+
695+
/* allocate struct for widget control data sizes and types */
696+
if (widget->num_kcontrols) {
697+
wdata = kcalloc(widget->num_kcontrols, sizeof(*wdata), GFP_KERNEL);
698+
if (!wdata)
699+
return -ENOMEM;
700+
701+
/* get possible component controls and get size of all pdata */
702+
ret = sof_get_control_data(scomp, widget, wdata, &ipc_data_size);
703+
if (ret < 0)
704+
goto out;
705+
}
706+
707+
ipc_size = sizeof(struct sof_ipc_comp_process) + ipc_data_size;
708+
709+
/* we are exceeding max ipc size, config needs to be sent separately */
710+
if (ipc_size > SOF_IPC_MSG_MAX_SIZE) {
711+
ipc_size -= ipc_data_size;
712+
ipc_data_size = 0;
713+
}
714+
715+
process = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id);
716+
if (!process) {
717+
ret = -ENOMEM;
718+
goto out;
719+
}
720+
721+
swidget->private = process;
722+
723+
/* configure iir IPC message */
724+
process->comp.type = type;
725+
process->config.hdr.size = sizeof(process->config);
726+
727+
/* parse one set of comp tokens */
728+
ret = sof_update_ipc_object(scomp, &process->config, SOF_COMP_TOKENS,
729+
swidget->tuples, swidget->num_tuples,
730+
sizeof(process->config), 1);
731+
if (ret < 0)
732+
goto err;
733+
734+
dev_dbg(scomp->dev, "loaded process %s\n", swidget->widget->name);
735+
sof_dbg_comp_config(scomp, &process->config);
736+
737+
/*
738+
* found private data in control, so copy it.
739+
* get possible component controls - get size of all pdata,
740+
* then memcpy with headers
741+
*/
742+
if (ipc_data_size) {
743+
for (i = 0; i < widget->num_kcontrols; i++) {
744+
memcpy(&process->data[offset],
745+
wdata[i].pdata->data,
746+
wdata[i].pdata->size);
747+
offset += wdata[i].pdata->size;
748+
}
749+
}
750+
751+
process->size = ipc_data_size;
752+
753+
kfree(wdata);
754+
755+
return 0;
756+
err:
757+
kfree(swidget->private);
758+
swidget->private = NULL;
759+
out:
760+
kfree(wdata);
761+
return ret;
762+
}
763+
764+
static enum sof_comp_type find_process_comp_type(enum sof_ipc_process_type type)
765+
{
766+
int i;
767+
768+
for (i = 0; i < ARRAY_SIZE(sof_process); i++) {
769+
if (sof_process[i].type == type)
770+
return sof_process[i].comp_type;
771+
}
772+
773+
return SOF_COMP_NONE;
774+
}
775+
776+
/*
777+
* Processing Component Topology - can be "effect", "codec", or general
778+
* "processing".
779+
*/
780+
781+
static int sof_widget_update_ipc_comp_process(struct snd_sof_widget *swidget)
782+
{
783+
struct snd_soc_component *scomp = swidget->scomp;
784+
struct sof_ipc_comp_process config;
785+
int ret;
786+
787+
memset(&config, 0, sizeof(config));
788+
config.comp.core = swidget->core;
789+
790+
/* parse one set of process tokens */
791+
ret = sof_update_ipc_object(scomp, &config, SOF_PROCESS_TOKENS, swidget->tuples,
792+
swidget->num_tuples, sizeof(config), 1);
793+
if (ret < 0)
794+
return ret;
795+
796+
/* now load process specific data and send IPC */
797+
return sof_process_load(scomp, swidget, find_process_comp_type(config.type));
798+
}
799+
561800
/* token list for each topology object */
562801
static enum sof_tokens host_token_list[] = {
563802
SOF_CORE_TOKENS,
@@ -604,6 +843,13 @@ static enum sof_tokens pga_token_list[] = {
604843
SOF_COMP_TOKENS,
605844
};
606845

846+
static enum sof_tokens process_token_list[] = {
847+
SOF_CORE_TOKENS,
848+
SOF_COMP_EXT_TOKENS,
849+
SOF_PROCESS_TOKENS,
850+
SOF_COMP_TOKENS,
851+
};
852+
607853
static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = {
608854
[snd_soc_dapm_aif_in] = {sof_ipc3_widget_setup_comp_host, sof_ipc3_widget_free_comp,
609855
host_token_list, ARRAY_SIZE(host_token_list), NULL},
@@ -630,6 +876,8 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TY
630876
[snd_soc_dapm_demux] = {sof_ipc3_widget_setup_comp_mux, sof_ipc3_widget_free_comp,
631877
comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list),
632878
NULL},
879+
[snd_soc_dapm_effect] = {sof_widget_update_ipc_comp_process, sof_ipc3_widget_free_comp,
880+
process_token_list, ARRAY_SIZE(process_token_list), NULL},
633881
};
634882

635883
static const struct sof_ipc_tplg_ops ipc3_tplg_ops = {

0 commit comments

Comments
 (0)