From 03365d6a58c47b3a3f2f964d0777493e293d7da4 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 27 Oct 2022 11:27:07 +0100 Subject: ASoC: qdsp6: audioreach: add support for more port connections AudioReach Modules can connect to other modules using source and destination port, and each module in theory can support up to 255 port connections. But in practice this limit is at max 8 ports at a time. So add support for allowing multiple port connections. This support is needed for more detailed graphs like ECNS, speaker protection and so. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20221027102710.21407-7-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- include/uapi/sound/snd_ar_tokens.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'include/uapi/sound') diff --git a/include/uapi/sound/snd_ar_tokens.h b/include/uapi/sound/snd_ar_tokens.h index 440c0725660b..b9b9093b4396 100644 --- a/include/uapi/sound/snd_ar_tokens.h +++ b/include/uapi/sound/snd_ar_tokens.h @@ -191,6 +191,33 @@ enum ar_event_types { #define AR_TKN_U32_MODULE_SRC_INSTANCE_ID 208 #define AR_TKN_U32_MODULE_DST_INSTANCE_ID 209 +#define AR_TKN_U32_MODULE_SRC_OP_PORT_ID1 210 +#define AR_TKN_U32_MODULE_DST_IN_PORT_ID1 211 +#define AR_TKN_U32_MODULE_DST_INSTANCE_ID1 212 + +#define AR_TKN_U32_MODULE_SRC_OP_PORT_ID2 213 +#define AR_TKN_U32_MODULE_DST_IN_PORT_ID2 214 +#define AR_TKN_U32_MODULE_DST_INSTANCE_ID2 215 + +#define AR_TKN_U32_MODULE_SRC_OP_PORT_ID3 216 +#define AR_TKN_U32_MODULE_DST_IN_PORT_ID3 217 +#define AR_TKN_U32_MODULE_DST_INSTANCE_ID3 218 + +#define AR_TKN_U32_MODULE_SRC_OP_PORT_ID4 219 +#define AR_TKN_U32_MODULE_DST_IN_PORT_ID4 220 +#define AR_TKN_U32_MODULE_DST_INSTANCE_ID4 221 + +#define AR_TKN_U32_MODULE_SRC_OP_PORT_ID5 222 +#define AR_TKN_U32_MODULE_DST_IN_PORT_ID5 223 +#define AR_TKN_U32_MODULE_DST_INSTANCE_ID5 224 + +#define AR_TKN_U32_MODULE_SRC_OP_PORT_ID6 225 +#define AR_TKN_U32_MODULE_DST_IN_PORT_ID6 226 +#define AR_TKN_U32_MODULE_DST_INSTANCE_ID6 227 + +#define AR_TKN_U32_MODULE_SRC_OP_PORT_ID7 228 +#define AR_TKN_U32_MODULE_DST_IN_PORT_ID7 229 +#define AR_TKN_U32_MODULE_DST_INSTANCE_ID7 230 #define AR_TKN_U32_MODULE_HW_IF_IDX 250 #define AR_TKN_U32_MODULE_HW_IF_TYPE 251 -- cgit v1.2.3 From 6327c7297fc86d2203ab31882152a9d0b049f7b2 Mon Sep 17 00:00:00 2001 From: Chao Song Date: Mon, 7 Nov 2022 10:57:04 +0200 Subject: ASoC: SOF: Add support for parsing the number of sink/source pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for parsing the number of sink/source pins per widget from topology. They will be used to determine the sink/source queue IDs during widget binding. Signed-off-by: Bard Liao Signed-off-by: Chao Song Suggested-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20221107085706.2550-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 2 ++ sound/soc/sof/sof-audio.h | 15 +++++++++++++++ sound/soc/sof/topology.c | 33 +++++++++++++++++++++++++++++---- 3 files changed, 46 insertions(+), 4 deletions(-) (limited to 'include/uapi/sound') diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 5caf75cadaf8..4f4881850650 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -88,6 +88,8 @@ #define SOF_TKN_COMP_CPC 406 #define SOF_TKN_COMP_IS_PAGES 409 #define SOF_TKN_COMP_NUM_AUDIO_FORMATS 410 +#define SOF_TKN_COMP_NUM_SINK_PINS 411 +#define SOF_TKN_COMP_NUM_SOURCE_PINS 412 /* SSP */ #define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500 diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 4284ea2f3a1f..dfca713f00df 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -23,6 +23,13 @@ #define SOF_AUDIO_PCM_DRV_NAME "sof-audio-component" +/* + * The ipc4 firmware only supports up to 8 sink or source pins + * per widget, because only 3 bits are used for queue(pin) ID + * in ipc4 protocol. + */ +#define SOF_WIDGET_MAX_NUM_PINS 8 + /* max number of FE PCMs before BEs */ #define SOF_BE_PCM_BASE 16 @@ -387,6 +394,14 @@ struct snd_sof_widget { int num_tuples; struct snd_sof_tuple *tuples; + /* + * The allowed range for num_sink/source_pins is [0, SOF_WIDGET_MAX_NUM_PINS]. + * Widgets may have zero sink or source pins, for example the tone widget has + * zero sink pins. + */ + u32 num_sink_pins; + u32 num_source_pins; + void *private; /* core does not touch this */ }; diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 38855dd60617..e839fcdc938b 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -392,6 +392,13 @@ static const struct sof_topology_token led_tokens[] = { offsetof(struct snd_sof_led_control, direction)}, }; +static const struct sof_topology_token comp_pin_tokens[] = { + {SOF_TKN_COMP_NUM_SINK_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct snd_sof_widget, num_sink_pins)}, + {SOF_TKN_COMP_NUM_SOURCE_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct snd_sof_widget, num_source_pins)}, +}; + /** * sof_parse_uuid_tokens - Parse multiple sets of UUID tokens * @scomp: pointer to soc component @@ -1259,6 +1266,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; const struct sof_ipc_tplg_widget_ops *widget_ops = ipc_tplg_ops->widget; + struct snd_soc_tplg_private *priv = &tw->priv; struct snd_sof_widget *swidget; struct snd_sof_dai *dai; enum sof_tokens *token_list; @@ -1277,10 +1285,27 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, swidget->pipeline_id = index; swidget->private = NULL; - dev_dbg(scomp->dev, "tplg: ready widget id %d pipe %d type %d name : %s stream %s\n", - swidget->comp_id, index, swidget->id, tw->name, - strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 - ? tw->sname : "none"); + ret = sof_parse_tokens(scomp, swidget, comp_pin_tokens, + ARRAY_SIZE(comp_pin_tokens), priv->array, + le32_to_cpu(priv->size)); + if (ret < 0) { + dev_err(scomp->dev, "failed to parse component pin tokens for %s\n", + w->name); + return ret; + } + + if (swidget->num_sink_pins > SOF_WIDGET_MAX_NUM_PINS || + swidget->num_source_pins > SOF_WIDGET_MAX_NUM_PINS) { + dev_err(scomp->dev, "invalid pins for %s: [sink: %d, src: %d]\n", + swidget->widget->name, swidget->num_sink_pins, swidget->num_source_pins); + return -EINVAL; + } + + dev_dbg(scomp->dev, + "tplg: widget %d (%s) is ready [type: %d, pipe: %d, pins: %d / %d, stream: %s]\n", + swidget->comp_id, w->name, swidget->id, index, + swidget->num_sink_pins, swidget->num_source_pins, + strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 ? w->sname : "none"); token_list = widget_ops[w->id].token_list; token_list_size = widget_ops[w->id].token_list_size; -- cgit v1.2.3 From 3b3acedbd0f30b822e05e5e51b646a67de0031fc Mon Sep 17 00:00:00 2001 From: Chao Song Date: Mon, 7 Nov 2022 10:57:05 +0200 Subject: ASoC: SOF: Add support to parse pin binding array from topology MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for parsing sink/source pin binding array per widget from topology. The pin binding arrays will be used to determine the source and sink queue IDs during widget binding for widget that requires special pin binding. An example of widget that requires special pin binding is the smart amplifier widget, its feedback sink pin has to be connected to a capture DAI copier for codec feedback, while the other sink pin has to be connected to a host DAI copier. Pin ID is required during widget binding for correct route setup. Conversely, the pin ID for 'generic' pins is not defined in the topology and will be allocated by the kernel dynamically. When only one pin is supported, the pin ID shall always be zero. When more than one pin is supported, the pin ID is determined with the ID allocation mechanism in the kernel. Signed-off-by: Chao Song Signed-off-by: Bard Liao Suggested-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20221107085706.2550-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 7 ++ sound/soc/sof/sof-audio.h | 21 ++++++ sound/soc/sof/topology.c | 139 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 163 insertions(+), 4 deletions(-) (limited to 'include/uapi/sound') diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 4f4881850650..f187dfbd9325 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -90,6 +90,13 @@ #define SOF_TKN_COMP_NUM_AUDIO_FORMATS 410 #define SOF_TKN_COMP_NUM_SINK_PINS 411 #define SOF_TKN_COMP_NUM_SOURCE_PINS 412 +/* + * The token for sink/source pin binding, it specifies the widget + * name that the sink/source pin is connected from/to. + */ +#define SOF_TKN_COMP_SINK_PIN_BINDING_WNAME 413 +#define SOF_TKN_COMP_SRC_PIN_BINDING_WNAME 414 + /* SSP */ #define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500 diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index dfca713f00df..efc80a5febc3 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -30,6 +30,10 @@ */ #define SOF_WIDGET_MAX_NUM_PINS 8 +/* The type of a widget pin is either sink or source */ +#define SOF_PIN_TYPE_SINK 0 +#define SOF_PIN_TYPE_SOURCE 1 + /* max number of FE PCMs before BEs */ #define SOF_BE_PCM_BASE 16 @@ -402,6 +406,22 @@ struct snd_sof_widget { u32 num_sink_pins; u32 num_source_pins; + /* + * The sink/source pin binding array, it takes the form of + * [widget_name_connected_to_pin0, widget_name_connected_to_pin1, ...], + * with the index as the queue ID. + * + * The array is used for special pin binding. Note that even if there + * is only one sink/source pin requires special pin binding, pin binding + * should be defined for all sink/source pins in topology, for pin(s) that + * are not used, give the value "NotConnected". + * + * If pin binding is not defined in topology, nothing to parse in the kernel, + * sink_pin_binding and src_pin_binding shall be NULL. + */ + char **sink_pin_binding; + char **src_pin_binding; + void *private; /* core does not touch this */ }; @@ -546,6 +566,7 @@ int get_token_u16(void *elem, void *object, u32 offset); int get_token_comp_format(void *elem, void *object, u32 offset); int get_token_dai_type(void *elem, void *object, u32 offset); int get_token_uuid(void *elem, void *object, u32 offset); +int get_token_string(void *elem, void *object, u32 offset); int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum sof_tokens token_id, struct snd_sof_tuple *tuples, int num_tuples, size_t object_size, int token_instance_num); diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index e839fcdc938b..3b1290d34131 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -360,6 +360,21 @@ int get_token_uuid(void *elem, void *object, u32 offset) return 0; } +/* + * The string gets from topology will be stored in heap, the owner only + * holds a char* member point to the heap. + */ +int get_token_string(void *elem, void *object, u32 offset) +{ + /* "dst" here points to the char* member of the owner */ + char **dst = (char **)((u8 *)object + offset); + + *dst = kstrdup(elem, GFP_KERNEL); + if (!*dst) + return -ENOMEM; + return 0; +}; + int get_token_comp_format(void *elem, void *object, u32 offset) { u32 *val = (u32 *)((u8 *)object + offset); @@ -399,6 +414,16 @@ static const struct sof_topology_token comp_pin_tokens[] = { offsetof(struct snd_sof_widget, num_source_pins)}, }; +static const struct sof_topology_token comp_sink_pin_binding_tokens[] = { + {SOF_TKN_COMP_SINK_PIN_BINDING_WNAME, SND_SOC_TPLG_TUPLE_TYPE_STRING, + get_token_string, 0}, +}; + +static const struct sof_topology_token comp_src_pin_binding_tokens[] = { + {SOF_TKN_COMP_SRC_PIN_BINDING_WNAME, SND_SOC_TPLG_TUPLE_TYPE_STRING, + get_token_string, 0}, +}; + /** * sof_parse_uuid_tokens - Parse multiple sets of UUID tokens * @scomp: pointer to soc component @@ -579,7 +604,7 @@ static int sof_parse_string_tokens(struct snd_soc_component *scomp, { struct snd_soc_tplg_vendor_string_elem *elem; int found = 0; - int i, j; + int i, j, ret; /* parse element by element */ for (i = 0; i < le32_to_cpu(array->num_elems); i++) { @@ -596,7 +621,9 @@ static int sof_parse_string_tokens(struct snd_soc_component *scomp, continue; /* matched - now load token */ - tokens[j].get_token(elem->string, object, offset + tokens[j].offset); + ret = tokens[j].get_token(elem->string, object, offset + tokens[j].offset); + if (ret < 0) + return ret; found++; } @@ -676,6 +703,7 @@ static int sof_parse_token_sets(struct snd_soc_component *scomp, int found = 0; int total = 0; int asize; + int ret; while (array_size > 0 && total < count * token_instance_num) { asize = le32_to_cpu(array->size); @@ -702,8 +730,15 @@ static int sof_parse_token_sets(struct snd_soc_component *scomp, array); break; case SND_SOC_TPLG_TUPLE_TYPE_STRING: - found += sof_parse_string_tokens(scomp, object, offset, tokens, count, - array); + + ret = sof_parse_string_tokens(scomp, object, offset, tokens, count, + array); + if (ret < 0) { + dev_err(scomp->dev, "error: no memory to copy string token\n"); + return ret; + } + + found += ret; break; case SND_SOC_TPLG_TUPLE_TYPE_BOOL: case SND_SOC_TPLG_TUPLE_TYPE_BYTE: @@ -1258,6 +1293,79 @@ err: return ret; } +static void sof_free_pin_binding(struct snd_sof_widget *swidget, + bool pin_type) +{ + char **pin_binding; + u32 num_pins; + int i; + + if (pin_type == SOF_PIN_TYPE_SINK) { + pin_binding = swidget->sink_pin_binding; + num_pins = swidget->num_sink_pins; + } else { + pin_binding = swidget->src_pin_binding; + num_pins = swidget->num_source_pins; + } + + if (pin_binding) { + for (i = 0; i < num_pins; i++) + kfree(pin_binding[i]); + } + + kfree(pin_binding); +} + +static int sof_parse_pin_binding(struct snd_sof_widget *swidget, + struct snd_soc_tplg_private *priv, bool pin_type) +{ + const struct sof_topology_token *pin_binding_token; + char *pin_binding[SOF_WIDGET_MAX_NUM_PINS]; + int token_count; + u32 num_pins; + char **pb; + int ret; + int i; + + if (pin_type == SOF_PIN_TYPE_SINK) { + num_pins = swidget->num_sink_pins; + pin_binding_token = comp_sink_pin_binding_tokens; + token_count = ARRAY_SIZE(comp_sink_pin_binding_tokens); + } else { + num_pins = swidget->num_source_pins; + pin_binding_token = comp_src_pin_binding_tokens; + token_count = ARRAY_SIZE(comp_src_pin_binding_tokens); + } + + memset(pin_binding, 0, SOF_WIDGET_MAX_NUM_PINS * sizeof(char *)); + ret = sof_parse_token_sets(swidget->scomp, pin_binding, pin_binding_token, + token_count, priv->array, le32_to_cpu(priv->size), + num_pins, sizeof(char *)); + if (ret < 0) + goto err; + + /* copy pin binding array to swidget only if it is defined in topology */ + if (pin_binding[0]) { + pb = kmemdup(pin_binding, num_pins * sizeof(char *), GFP_KERNEL); + if (!pb) { + ret = -ENOMEM; + goto err; + } + if (pin_type == SOF_PIN_TYPE_SINK) + swidget->sink_pin_binding = pb; + else + swidget->src_pin_binding = pb; + } + + return 0; + +err: + for (i = 0; i < num_pins; i++) + kfree(pin_binding[i]); + + return ret; +} + /* external widget init - used for any driver specific init */ static int sof_widget_ready(struct snd_soc_component *scomp, int index, struct snd_soc_dapm_widget *w, @@ -1301,6 +1409,26 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, return -EINVAL; } + if (swidget->num_sink_pins > 1) { + ret = sof_parse_pin_binding(swidget, priv, SOF_PIN_TYPE_SINK); + /* on parsing error, pin binding is not allocated, nothing to free. */ + if (ret < 0) { + dev_err(scomp->dev, "failed to parse sink pin binding for %s\n", + w->name); + return ret; + } + } + + if (swidget->num_source_pins > 1) { + ret = sof_parse_pin_binding(swidget, priv, SOF_PIN_TYPE_SOURCE); + /* on parsing error, pin binding is not allocated, nothing to free. */ + if (ret < 0) { + dev_err(scomp->dev, "failed to parse source pin binding for %s\n", + w->name); + return ret; + } + } + dev_dbg(scomp->dev, "tplg: widget %d (%s) is ready [type: %d, pipe: %d, pins: %d / %d, stream: %s]\n", swidget->comp_id, w->name, swidget->id, index, @@ -1496,6 +1624,9 @@ out: if (widget_ops[swidget->id].ipc_free) widget_ops[swidget->id].ipc_free(swidget); + sof_free_pin_binding(swidget, SOF_PIN_TYPE_SINK); + sof_free_pin_binding(swidget, SOF_PIN_TYPE_SOURCE); + kfree(swidget->tuples); /* remove and free swidget object */ -- cgit v1.2.3 From 75af41991955205fa0958feb587ce22b35aaa7b0 Mon Sep 17 00:00:00 2001 From: V sujith kumar Reddy Date: Tue, 29 Nov 2022 15:30:59 +0530 Subject: ASoC: SOF: Add DAI configuration support for AMD platforms. Add support for configuring sp and hs DAI from topology. Signed-off-by: V sujith kumar Reddy Link: https://lore.kernel.org/r/20221129100102.826781-1-vsujithkumar.reddy@amd.corp-partner.google.com Signed-off-by: Mark Brown --- include/sound/sof/dai-amd.h | 1 + include/sound/sof/dai.h | 2 ++ include/uapi/sound/sof/tokens.h | 5 +++++ sound/soc/sof/ipc3-pcm.c | 2 ++ sound/soc/sof/ipc3-topology.c | 36 ++++++++++++++++++++++++++++-------- sound/soc/sof/sof-audio.h | 1 + sound/soc/sof/topology.c | 10 ++++++++++ 7 files changed, 49 insertions(+), 8 deletions(-) (limited to 'include/uapi/sound') diff --git a/include/sound/sof/dai-amd.h b/include/sound/sof/dai-amd.h index 92f45c180b7c..9df7ac824efe 100644 --- a/include/sound/sof/dai-amd.h +++ b/include/sound/sof/dai-amd.h @@ -17,6 +17,7 @@ struct sof_ipc_dai_acp_params { uint32_t fsync_rate; /* FSYNC frequency in Hz */ uint32_t tdm_slots; + uint32_t tdm_mode; } __packed; /* ACPDMIC Configuration Request - SOF_IPC_DAI_AMD_CONFIG */ diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h index 9fbd3832bcdc..3041f5805b7b 100644 --- a/include/sound/sof/dai.h +++ b/include/sound/sof/dai.h @@ -86,6 +86,8 @@ enum sof_ipc_dai_type { SOF_DAI_AMD_DMIC, /**< AMD ACP DMIC */ SOF_DAI_MEDIATEK_AFE, /**< Mediatek AFE */ SOF_DAI_AMD_HS, /**< Amd HS */ + SOF_DAI_AMD_SP_VIRTUAL, /**< AMD ACP SP VIRTUAL */ + SOF_DAI_AMD_HS_VIRTUAL, /**< AMD ACP HS VIRTUAL */ }; /* general purpose DAI configuration */ diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index f187dfbd9325..bacaf8a6317e 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -198,4 +198,9 @@ /* COPIER */ #define SOF_TKN_INTEL_COPIER_NODE_TYPE 1980 +/* ACP I2S */ +#define SOF_TKN_AMD_ACPI2S_RATE 1700 +#define SOF_TKN_AMD_ACPI2S_CH 1701 +#define SOF_TKN_AMD_ACPI2S_TDM_MODE 1702 + #endif diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index dad57bef38f6..f10bfc9bd5cb 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -336,6 +336,7 @@ static int sof_ipc3_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, channels->min, channels->max); break; case SOF_DAI_AMD_SP: + case SOF_DAI_AMD_SP_VIRTUAL: rate->min = private->dai_config->acpsp.fsync_rate; rate->max = private->dai_config->acpsp.fsync_rate; channels->min = private->dai_config->acpsp.tdm_slots; @@ -347,6 +348,7 @@ static int sof_ipc3_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, channels->min, channels->max); break; case SOF_DAI_AMD_HS: + case SOF_DAI_AMD_HS_VIRTUAL: rate->min = private->dai_config->acphs.fsync_rate; rate->max = private->dai_config->acphs.fsync_rate; channels->min = private->dai_config->acphs.tdm_slots; diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index 0720e1eae084..b94cc40485ed 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -276,6 +276,16 @@ static const struct sof_topology_token acpdmic_tokens[] = { offsetof(struct sof_ipc_dai_acpdmic_params, pdm_ch)}, }; +/* ACPI2S */ +static const struct sof_topology_token acpi2s_tokens[] = { + {SOF_TKN_AMD_ACPI2S_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_acp_params, fsync_rate)}, + {SOF_TKN_AMD_ACPI2S_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_acp_params, tdm_slots)}, + {SOF_TKN_AMD_ACPI2S_TDM_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_acp_params, tdm_mode)}, +}; + /* Core tokens */ static const struct sof_topology_token core_tokens[] = { {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, @@ -311,6 +321,7 @@ static const struct sof_token_info ipc3_token_list[SOF_TOKEN_COUNT] = { [SOF_SAI_TOKENS] = {"SAI tokens", sai_tokens, ARRAY_SIZE(sai_tokens)}, [SOF_AFE_TOKENS] = {"AFE tokens", afe_tokens, ARRAY_SIZE(afe_tokens)}, [SOF_ACPDMIC_TOKENS] = {"ACPDMIC tokens", acpdmic_tokens, ARRAY_SIZE(acpdmic_tokens)}, + [SOF_ACPI2S_TOKENS] = {"ACPI2S tokens", acpi2s_tokens, ARRAY_SIZE(acpi2s_tokens)}, }; /** @@ -1193,6 +1204,7 @@ static int sof_link_acp_sp_load(struct snd_soc_component *scomp, struct snd_sof_ struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; struct sof_dai_private_data *private = dai->private; u32 size = sizeof(*config); + int ret; /* handle master/slave and inverted clocks */ sof_dai_set_format(hw_config, config); @@ -1201,12 +1213,15 @@ static int sof_link_acp_sp_load(struct snd_soc_component *scomp, struct snd_sof_ memset(&config->acpsp, 0, sizeof(config->acpsp)); config->hdr.size = size; - config->acpsp.fsync_rate = le32_to_cpu(hw_config->fsync_rate); - config->acpsp.tdm_slots = le32_to_cpu(hw_config->tdm_slots); + ret = sof_update_ipc_object(scomp, &config->acpsp, SOF_ACPI2S_TOKENS, slink->tuples, + slink->num_tuples, size, slink->num_hw_configs); + if (ret < 0) + return ret; - dev_info(scomp->dev, "ACP_SP config ACP%d channel %d rate %d\n", + + dev_info(scomp->dev, "ACP_SP config ACP%d channel %d rate %d tdm_mode %d\n", config->dai_index, config->acpsp.tdm_slots, - config->acpsp.fsync_rate); + config->acpsp.fsync_rate, config->acpsp.tdm_mode); dai->number_configs = 1; dai->current_config = 0; @@ -1223,6 +1238,7 @@ static int sof_link_acp_hs_load(struct snd_soc_component *scomp, struct snd_sof_ struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; struct sof_dai_private_data *private = dai->private; u32 size = sizeof(*config); + int ret; /* Configures the DAI hardware format and inverted clocks */ sof_dai_set_format(hw_config, config); @@ -1231,12 +1247,14 @@ static int sof_link_acp_hs_load(struct snd_soc_component *scomp, struct snd_sof_ memset(&config->acphs, 0, sizeof(config->acphs)); config->hdr.size = size; - config->acphs.fsync_rate = le32_to_cpu(hw_config->fsync_rate); - config->acphs.tdm_slots = le32_to_cpu(hw_config->tdm_slots); + ret = sof_update_ipc_object(scomp, &config->acphs, SOF_ACPI2S_TOKENS, slink->tuples, + slink->num_tuples, size, slink->num_hw_configs); + if (ret < 0) + return ret; - dev_info(scomp->dev, "ACP_HS config ACP%d channel %d rate %d\n", + dev_info(scomp->dev, "ACP_HS config ACP%d channel %d rate %d tdm_mode %d\n", config->dai_index, config->acphs.tdm_slots, - config->acphs.fsync_rate); + config->acphs.fsync_rate, config->acphs.tdm_mode); dai->number_configs = 1; dai->current_config = 0; @@ -1545,9 +1563,11 @@ static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget) ret = sof_link_acp_bt_load(scomp, slink, config, dai); break; case SOF_DAI_AMD_SP: + case SOF_DAI_AMD_SP_VIRTUAL: ret = sof_link_acp_sp_load(scomp, slink, config, dai); break; case SOF_DAI_AMD_HS: + case SOF_DAI_AMD_HS_VIRTUAL: ret = sof_link_acp_hs_load(scomp, slink, config, dai); break; case SOF_DAI_AMD_DMIC: diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 1b5b3ea53a6e..29cf951e3526 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -248,6 +248,7 @@ enum sof_tokens { SOF_COPIER_FORMAT_TOKENS, SOF_GAIN_TOKENS, SOF_ACPDMIC_TOKENS, + SOF_ACPI2S_TOKENS, /* this should be the last */ SOF_TOKEN_COUNT, diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 9d9fcaa2a948..c668bd9d21ec 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -289,6 +289,9 @@ static const struct sof_dai_types sof_dais[] = { {"ACPDMIC", SOF_DAI_AMD_DMIC}, {"ACPHS", SOF_DAI_AMD_HS}, {"AFE", SOF_DAI_MEDIATEK_AFE}, + {"ACPSP_VIRTUAL", SOF_DAI_AMD_SP_VIRTUAL}, + {"ACPHS_VIRTUAL", SOF_DAI_AMD_HS_VIRTUAL}, + }; static enum sof_ipc_dai_type find_dai(const char *name) @@ -1895,6 +1898,13 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_ token_id = SOF_ACPDMIC_TOKENS; num_tuples += token_list[SOF_ACPDMIC_TOKENS].count; break; + case SOF_DAI_AMD_SP: + case SOF_DAI_AMD_HS: + case SOF_DAI_AMD_SP_VIRTUAL: + case SOF_DAI_AMD_HS_VIRTUAL: + token_id = SOF_ACPI2S_TOKENS; + num_tuples += token_list[SOF_ACPI2S_TOKENS].count; + break; default: break; } -- cgit v1.2.3