mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
ASoC: SOF: ipc4-topology: Configure copier sink format
Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>: In a course of creating complicated topologies where multiple output pins of a copier is enabled, we have discovered that additional configuration needs to be sent to the firmware to make the use cases working.
This commit is contained in:
commit
67b690b356
3 changed files with 119 additions and 9 deletions
|
@ -1742,6 +1742,55 @@ static void sof_ipc4_put_queue_id(struct snd_sof_widget *swidget, int queue_id,
|
|||
ida_free(queue_ida, queue_id);
|
||||
}
|
||||
|
||||
static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev,
|
||||
struct snd_sof_widget *src_widget,
|
||||
struct snd_sof_widget *sink_widget,
|
||||
int sink_id)
|
||||
{
|
||||
struct sof_ipc4_base_module_cfg *sink_config = sink_widget->private;
|
||||
struct sof_ipc4_base_module_cfg *src_config;
|
||||
struct sof_ipc4_copier_config_set_sink_format format;
|
||||
struct sof_ipc4_fw_module *fw_module;
|
||||
struct sof_ipc4_msg msg = {{ 0 }};
|
||||
u32 header, extension;
|
||||
|
||||
dev_dbg(sdev->dev, "%s set copier sink %d format\n",
|
||||
src_widget->widget->name, sink_id);
|
||||
|
||||
if (WIDGET_IS_DAI(src_widget->id)) {
|
||||
struct snd_sof_dai *dai = src_widget->private;
|
||||
|
||||
src_config = dai->private;
|
||||
} else {
|
||||
src_config = src_widget->private;
|
||||
}
|
||||
|
||||
fw_module = src_widget->module_info;
|
||||
|
||||
format.sink_id = sink_id;
|
||||
memcpy(&format.source_fmt, &src_config->audio_fmt, sizeof(format.source_fmt));
|
||||
memcpy(&format.sink_fmt, &sink_config->audio_fmt, sizeof(format.sink_fmt));
|
||||
msg.data_size = sizeof(format);
|
||||
msg.data_ptr = &format;
|
||||
|
||||
header = fw_module->man4_module_entry.id;
|
||||
header |= SOF_IPC4_MOD_INSTANCE(src_widget->instance_id);
|
||||
header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET);
|
||||
header |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
|
||||
header |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
|
||||
|
||||
extension = SOF_IPC4_MOD_EXT_MSG_SIZE(msg.data_size);
|
||||
extension |=
|
||||
SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT);
|
||||
extension |= SOF_IPC4_MOD_EXT_MSG_LAST_BLOCK(1);
|
||||
extension |= SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(1);
|
||||
|
||||
msg.primary = header;
|
||||
msg.extension = extension;
|
||||
|
||||
return sof_ipc_tx_message(sdev->ipc, &msg, msg.data_size, NULL, 0);
|
||||
}
|
||||
|
||||
static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute)
|
||||
{
|
||||
struct snd_sof_widget *src_widget = sroute->src_widget;
|
||||
|
@ -1770,6 +1819,17 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *
|
|||
return sroute->dst_queue_id;
|
||||
}
|
||||
|
||||
/* Pin 0 format is already set during copier module init */
|
||||
if (sroute->src_queue_id > 0 && WIDGET_IS_COPIER(src_widget->id)) {
|
||||
ret = sof_ipc4_set_copier_sink_format(sdev, src_widget, sink_widget,
|
||||
sroute->src_queue_id);
|
||||
if (ret < 0) {
|
||||
dev_err(sdev->dev, "failed to set sink format for %s source queue ID %d\n",
|
||||
src_widget->widget->name, sroute->src_queue_id);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(sdev->dev, "bind %s:%d -> %s:%d\n",
|
||||
src_widget->widget->name, sroute->src_queue_id,
|
||||
sink_widget->widget->name, sroute->dst_queue_id);
|
||||
|
@ -1790,16 +1850,18 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *
|
|||
|
||||
ret = sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(sdev->dev, "%s: failed to bind modules %s -> %s\n",
|
||||
__func__, src_widget->widget->name, sink_widget->widget->name);
|
||||
|
||||
sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id,
|
||||
SOF_PIN_TYPE_SOURCE);
|
||||
sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id,
|
||||
SOF_PIN_TYPE_SINK);
|
||||
dev_err(sdev->dev, "failed to bind modules %s:%d -> %s:%d\n",
|
||||
src_widget->widget->name, sroute->src_queue_id,
|
||||
sink_widget->widget->name, sroute->dst_queue_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
out:
|
||||
sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_SOURCE);
|
||||
sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_SINK);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *sroute)
|
||||
|
@ -1839,8 +1901,9 @@ static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *s
|
|||
|
||||
ret = sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0);
|
||||
if (ret < 0)
|
||||
dev_err(sdev->dev, "failed to unbind modules %s -> %s\n",
|
||||
src_widget->widget->name, sink_widget->widget->name);
|
||||
dev_err(sdev->dev, "failed to unbind modules %s:%d -> %s:%d\n",
|
||||
src_widget->widget->name, sroute->src_queue_id,
|
||||
sink_widget->widget->name, sroute->dst_queue_id);
|
||||
out:
|
||||
sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_SINK);
|
||||
sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_SOURCE);
|
||||
|
|
|
@ -66,6 +66,52 @@
|
|||
/* A magic number from FW */
|
||||
#define ALH_MULTI_GTW_COUNT 8
|
||||
|
||||
enum sof_ipc4_copier_module_config_params {
|
||||
/*
|
||||
* Use LARGE_CONFIG_SET to initialize timestamp event. Ipc mailbox must
|
||||
* contain properly built CopierConfigTimestampInitData struct.
|
||||
*/
|
||||
SOF_IPC4_COPIER_MODULE_CFG_PARAM_TIMESTAMP_INIT = 1,
|
||||
/*
|
||||
* Use LARGE_CONFIG_SET to initialize copier sink. Ipc mailbox must contain
|
||||
* properly built CopierConfigSetSinkFormat struct.
|
||||
*/
|
||||
SOF_IPC4_COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT,
|
||||
/*
|
||||
* Use LARGE_CONFIG_SET to initialize and enable on Copier data segment
|
||||
* event. Ipc mailbox must contain properly built DataSegmentEnabled struct.
|
||||
*/
|
||||
SOF_IPC4_COPIER_MODULE_CFG_PARAM_DATA_SEGMENT_ENABLED,
|
||||
/*
|
||||
* Use LARGE_CONFIG_GET to retrieve Linear Link Position (LLP) value for non
|
||||
* HD-A gateways.
|
||||
*/
|
||||
SOF_IPC4_COPIER_MODULE_CFG_PARAM_LLP_READING,
|
||||
/*
|
||||
* Use LARGE_CONFIG_GET to retrieve Linear Link Position (LLP) value for non
|
||||
* HD-A gateways and corresponding total processed data
|
||||
*/
|
||||
SOF_IPC4_COPIER_MODULE_CFG_PARAM_LLP_READING_EXTENDED,
|
||||
/*
|
||||
* Use LARGE_CONFIG_SET to setup attenuation on output pins. Data is just uint32_t.
|
||||
* note Config is only allowed when output pin is set up for 32bit and source
|
||||
* is connected to Gateway
|
||||
*/
|
||||
SOF_IPC4_COPIER_MODULE_CFG_ATTENUATION,
|
||||
};
|
||||
|
||||
struct sof_ipc4_copier_config_set_sink_format {
|
||||
/* Id of sink */
|
||||
u32 sink_id;
|
||||
/*
|
||||
* Input format used by the source
|
||||
* attention must be the same as present if already initialized.
|
||||
*/
|
||||
struct sof_ipc4_audio_format source_fmt;
|
||||
/* Output format used by the sink */
|
||||
struct sof_ipc4_audio_format sink_fmt;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/**
|
||||
* struct sof_ipc4_pipeline - pipeline config data
|
||||
* @priority: Priority of this pipeline
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#define WIDGET_IS_DAI(id) ((id) == snd_soc_dapm_dai_in || (id) == snd_soc_dapm_dai_out)
|
||||
#define WIDGET_IS_AIF(id) ((id) == snd_soc_dapm_aif_in || (id) == snd_soc_dapm_aif_out)
|
||||
#define WIDGET_IS_AIF_OR_DAI(id) (WIDGET_IS_DAI(id) || WIDGET_IS_AIF(id))
|
||||
#define WIDGET_IS_COPIER(id) (WIDGET_IS_AIF_OR_DAI(id) || (id) == snd_soc_dapm_buffer)
|
||||
|
||||
#define SOF_DAI_CLK_INTEL_SSP_MCLK 0
|
||||
#define SOF_DAI_CLK_INTEL_SSP_BCLK 1
|
||||
|
|
Loading…
Reference in a new issue