[PATCH 00/11] ASoC: SOF: Intel: updates and cleanups
Set of updates for IPC3, IPC4, MTL support and cleanups for the topology filename override which was broken for HDaudio platforms.
It may be too late for 5.20, it's ok if these patches are applied in the next cycle.
The topology override depends on the patch "ASoC: SOF: Intel: enable dmic handling with 2 or fewer SoundWire links" shared in a separate patchset.
Bard Liao (1): ASoC: SOF: ipc4-topology: move ida allocate/free to widget_setup/free
Peter Ujfalusi (2): ASoC: SOF: ipc3-loader: Print out the non matching ext_man magic number ASoC: SOF: Intel: atom: don't keep a temporary string in fixup_tplg_name
Pierre-Louis Bossart (4): ASoC: SOF: Intel: hda: don't set fw_filename ASoC: SOF: Intel: hda: only fixup topology name if not set already ASoC: SOF: probes: rename assign/free callbacks as startup/shutdown ASoC: SOF: Intel: hda-stream: test DMA buffer first in hw_params
Rander Wang (3): ASoC: SOF: ipc4-pcm: set pcm rate to dai setting ASoC: SOF: add ipc4 SRC module support ASoC: SOF: ipc4-topology: set domain bit based on dp domain type
Yong Zhi (1): ASoC: SOF: Intel: MTL: remove redundant snd_sof_dsp_read() call
sound/soc/sof/intel/atom.c | 16 +-- sound/soc/sof/intel/hda-probes.c | 16 +-- sound/soc/sof/intel/hda-stream.c | 15 ++- sound/soc/sof/intel/hda.c | 71 +++++++++----- sound/soc/sof/intel/mtl.c | 13 +-- sound/soc/sof/ipc3-loader.c | 6 +- sound/soc/sof/ipc4-pcm.c | 4 + sound/soc/sof/ipc4-topology.c | 156 +++++++++++++++++++++++++----- sound/soc/sof/ipc4-topology.h | 27 +++++- sound/soc/sof/sof-client-probes.c | 8 +- sound/soc/sof/sof-client-probes.h | 8 +- 11 files changed, 250 insertions(+), 90 deletions(-)
From: Yong Zhi yong.zhi@intel.com
Drop redundant CPA bit check after polling the same condition.
Fixes: 064520e8aeaa ("ASoC: SOF: Intel: Add support for MeteorLake (MTL)") Reviewed-by: Chao Song chao.song@intel.com Reviewed-by: Bard Liao yung-chuan.liao@linux.intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Signed-off-by: Yong Zhi yong.zhi@intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/sof/intel/mtl.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index a5e244ea0688..96239ebb1eed 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -372,20 +372,9 @@ static int mtl_dsp_core_power_up(struct snd_sof_dev *sdev, int core) ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl, (dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); - if (ret < 0) { + if (ret < 0) dev_err(sdev->dev, "%s: timeout on MTL_DSP2CXCTL_PRIMARY_CORE read\n", __func__); - return ret; - } - - /* did core power up ? */ - dspcxctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE); - if ((dspcxctl & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK) - != MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK) { - dev_err(sdev->dev, "power up core failed core %d adspcs %#x\n", - core, dspcxctl); - ret = -EIO; - }
return ret; }
From: Bard Liao yung-chuan.liao@linux.intel.com
The existing code allocate/release instance_id in widget ipc_prepare/ ipc_unprepare callbacks and creating widget with the instance_id in tplg widget_setup callback. In the case of multiple widgets connecting to one widget, the ipc_unprepare will be invoked for all the widgets in the path including the widget which is still in use. As a result, the instance_id is released in the ipc_unprepare callback, but the widget is still in use and the instance_id will be reused by a new widget when we start the PCM again. Moving the ida work from ipc_prepare/ipc_unprepare to widget_setup/free can avoid such problem.
Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/sof/ipc4-topology.c | 36 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 20 deletions(-)
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 22ea628d78d0..f77091918118 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -891,7 +891,6 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev,
static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget) { - struct sof_ipc4_fw_module *fw_module = swidget->module_info; struct sof_ipc4_copier *ipc4_copier = NULL; struct snd_sof_widget *pipe_widget; struct sof_ipc4_pipeline *pipeline; @@ -925,8 +924,6 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget) ipc4_copier->ipc_config_data = NULL; ipc4_copier->ipc_config_size = 0; } - - ida_free(&fw_module->m_ida, swidget->instance_id); }
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT) @@ -1254,15 +1251,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* update pipeline memory usage */ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &copier_data->base_config);
- /* assign instance ID */ - return sof_ipc4_widget_assign_instance_id(sdev, swidget); -} - -static void sof_ipc4_unprepare_generic_module(struct snd_sof_widget *swidget) -{ - struct sof_ipc4_fw_module *fw_module = swidget->module_info; - - ida_free(&fw_module->m_ida, swidget->instance_id); + return 0; }
static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, @@ -1287,8 +1276,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, /* update pipeline memory usage */ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &gain->base_config);
- /* assign instance ID */ - return sof_ipc4_widget_assign_instance_id(sdev, swidget); + return 0; }
static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, @@ -1314,8 +1302,7 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, /* update pipeline memory usage */ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &mixer->base_config);
- /* assign instance ID */ - return sof_ipc4_widget_assign_instance_id(sdev, swidget); + return 0; }
static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) @@ -1373,8 +1360,6 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget u32 ipc_size = 0; int ret;
- dev_dbg(sdev->dev, "Create widget %s instance %d - pipe %d - core %d\n", - swidget->widget->name, swidget->instance_id, swidget->pipeline_id, swidget->core);
switch (swidget->id) { case snd_soc_dapm_scheduler: @@ -1436,6 +1421,12 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget }
if (swidget->id != snd_soc_dapm_scheduler) { + ret = sof_ipc4_widget_assign_instance_id(sdev, swidget); + if (ret < 0) { + dev_err(sdev->dev, "failed to assign instance id for %s\n", + swidget->widget->name); + return ret; + } pipeline = pipe_widget->private; msg->primary &= ~SOF_IPC4_MOD_INSTANCE_MASK; msg->primary |= SOF_IPC4_MOD_INSTANCE(swidget->instance_id); @@ -1445,6 +1436,8 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget msg->extension &= ~SOF_IPC4_MOD_EXT_DOMAIN_MASK; msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(pipeline->lp_mode); } + dev_dbg(sdev->dev, "Create widget %s instance %d - pipe %d - core %d\n", + swidget->widget->name, swidget->instance_id, swidget->pipeline_id, swidget->core);
msg->data_size = ipc_size; msg->data_ptr = ipc_data; @@ -1458,6 +1451,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { + struct sof_ipc4_fw_module *fw_module = swidget->module_info; int ret = 0;
/* freeing a pipeline frees all the widgets associated with it */ @@ -1480,6 +1474,8 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget
pipeline->mem_usage = 0; pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED; + } else { + ida_free(&fw_module->m_ida, swidget->instance_id); }
return ret; @@ -1789,11 +1785,11 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY [snd_soc_dapm_pga] = {sof_ipc4_widget_setup_comp_pga, sof_ipc4_widget_free_comp_pga, pga_token_list, ARRAY_SIZE(pga_token_list), NULL, sof_ipc4_prepare_gain_module, - sof_ipc4_unprepare_generic_module}, + NULL}, [snd_soc_dapm_mixer] = {sof_ipc4_widget_setup_comp_mixer, sof_ipc4_widget_free_comp_mixer, mixer_token_list, ARRAY_SIZE(mixer_token_list), NULL, sof_ipc4_prepare_mixer_module, - sof_ipc4_unprepare_generic_module}, + NULL}, };
const struct sof_ipc_tplg_ops ipc4_tplg_ops = {
From: Rander Wang rander.wang@intel.com
Dsp converts pcm rate to the one defined by dai. When SRC is used, the pcm runtime rate is different with dai rate and we need to fix it up for BE components.
Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Signed-off-by: Rander Wang rander.wang@intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/sof/ipc4-pcm.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 6a702f9dc065..732872395980 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -179,6 +179,7 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, { struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name); + struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct sof_ipc4_copier *ipc4_copier; @@ -201,6 +202,9 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);
+ rate->min = ipc4_copier->available_fmt.base_config->audio_fmt.sampling_frequency; + rate->max = rate->min; + /* * Set trigger order for capture to SND_SOC_DPCM_TRIGGER_PRE. This is required * to ensure that the BE DAI pipeline gets stopped/suspended before the FE DAI
From: Rander Wang rander.wang@intel.com
SRC module only needs two parameters : base module config and sink rate. This patch adds prepare and setup for SRC widgets.
Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Signed-off-by: Rander Wang rander.wang@intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/sof/ipc4-topology.c | 114 +++++++++++++++++++++++++++++++++- sound/soc/sof/ipc4-topology.h | 14 +++++ 2 files changed, 127 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index f77091918118..47291fa3f166 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -111,6 +111,12 @@ static const struct sof_topology_token gain_tokens[] = { get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)}, };
+/* SRC */ +static const struct sof_topology_token src_tokens[] = { + {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_src, sink_rate)}, +}; + static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { [SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)}, [SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)}, @@ -134,6 +140,7 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { [SOF_AUDIO_FMT_NUM_TOKENS] = {"IPC4 Audio format number tokens", ipc4_audio_fmt_num_tokens, ARRAY_SIZE(ipc4_audio_fmt_num_tokens)}, [SOF_GAIN_TOKENS] = {"Gain tokens", gain_tokens, ARRAY_SIZE(gain_tokens)}, + [SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)}, };
static void sof_ipc4_dbg_audio_format(struct device *dev, @@ -740,6 +747,58 @@ static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget) return ret; }
+static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget) +{ + struct snd_soc_component *scomp = swidget->scomp; + struct sof_ipc4_src *src; + int ret; + + dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name); + + src = kzalloc(sizeof(*src), GFP_KERNEL); + if (!src) + return -ENOMEM; + + swidget->private = src; + + /* The out_audio_fmt in topology is ignored as it is not required by SRC */ + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, false); + if (ret) + goto err; + + ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples, + swidget->num_tuples, sizeof(src), 1); + if (ret) { + dev_err(scomp->dev, "Parsing SRC tokens failed\n"); + goto err; + } + + dev_dbg(scomp->dev, "SRC sink rate %d\n", src->sink_rate); + + ret = sof_ipc4_widget_setup_msg(swidget, &src->msg); + if (ret) + goto err; + + return 0; +err: + sof_ipc4_free_audio_fmt(&src->available_fmt); + kfree(src); + swidget->private = NULL; + return ret; +} + +static void sof_ipc4_widget_free_comp_src(struct snd_sof_widget *swidget) +{ + struct sof_ipc4_src *src = swidget->private; + + if (!src) + return; + + sof_ipc4_free_audio_fmt(&src->available_fmt); + kfree(swidget->private); + swidget->private = NULL; +} + static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget) { struct sof_ipc4_mixer *mixer = swidget->private; @@ -1305,6 +1364,37 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, return 0; }
+static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, + struct snd_pcm_hw_params *fe_params, + struct snd_sof_platform_stream_params *platform_params, + struct snd_pcm_hw_params *pipeline_params, int dir) +{ + struct snd_soc_component *scomp = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_ipc4_src *src = swidget->private; + struct snd_interval *rate; + int ret; + + src->available_fmt.ref_audio_fmt = &src->available_fmt.base_config->audio_fmt; + + /* output format is not required to be sent to the FW for SRC */ + ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, + NULL, pipeline_params, &src->available_fmt, + sizeof(src->base_config)); + if (ret < 0) + return ret; + + /* update pipeline memory usage */ + sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &src->base_config); + + /* update pipeline_params for sink widgets */ + rate = hw_param_interval(pipeline_params, SNDRV_PCM_HW_PARAM_RATE); + rate->min = src->sink_rate; + rate->max = rate->min; + + return 0; +} + static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) { struct sof_ipc4_control_data *control_data; @@ -1360,7 +1450,6 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget u32 ipc_size = 0; int ret;
- switch (swidget->id) { case snd_soc_dapm_scheduler: pipeline = swidget->private; @@ -1415,6 +1504,16 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget msg = &mixer->msg; break; } + case snd_soc_dapm_src: + { + struct sof_ipc4_src *src = swidget->private; + + ipc_size = sizeof(struct sof_ipc4_base_module_cfg) + sizeof(src->sink_rate); + ipc_data = src; + + msg = &src->msg; + break; + } default: dev_err(sdev->dev, "widget type %d not supported", swidget->id); return -EINVAL; @@ -1762,6 +1861,15 @@ static enum sof_tokens mixer_token_list[] = { SOF_COMP_EXT_TOKENS, };
+static enum sof_tokens src_token_list[] = { + SOF_COMP_TOKENS, + SOF_SRC_TOKENS, + SOF_AUDIO_FMT_NUM_TOKENS, + SOF_IN_AUDIO_FORMAT_TOKENS, + SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, + SOF_COMP_EXT_TOKENS, +}; + static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = { [snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm, host_token_list, ARRAY_SIZE(host_token_list), NULL, @@ -1790,6 +1898,10 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY mixer_token_list, ARRAY_SIZE(mixer_token_list), NULL, sof_ipc4_prepare_mixer_module, NULL}, + [snd_soc_dapm_src] = {sof_ipc4_widget_setup_comp_src, sof_ipc4_widget_free_comp_src, + src_token_list, ARRAY_SIZE(src_token_list), + NULL, sof_ipc4_prepare_src_module, + NULL}, };
const struct sof_ipc_tplg_ops ipc4_tplg_ops = { diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 3bc2fe38c733..56ab80e722ce 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -242,4 +242,18 @@ struct sof_ipc4_mixer { struct sof_ipc4_msg msg; };
+/** + * struct sof_ipc4_src SRC config data + * @base_config: IPC base config data + * @sink_rate: Output rate for sink module + * @available_fmt: Available audio format + * @msg: IPC4 message struct containing header and data info + */ +struct sof_ipc4_src { + struct sof_ipc4_base_module_cfg base_config; + uint32_t sink_rate; + struct sof_ipc4_available_audio_format available_fmt; + struct sof_ipc4_msg msg; +}; + #endif
From: Rander Wang rander.wang@intel.com
Currently the domain bit in ipc msg for module initialization is set to lp (low power) mode for pipeline. This is not correct since it is for module domain type: ll domain or dp domain which are for scheduler in fw. If the domain bit is set to 1 fw will process the module in dp domain or deal it with ll domain. So set domain bit based on dp domain setting.
Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Signed-off-by: Rander Wang rander.wang@intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/sof/ipc4-topology.c | 6 ++++-- sound/soc/sof/ipc4-topology.h | 13 ++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 47291fa3f166..af072b484a60 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -314,6 +314,7 @@ static int sof_ipc4_widget_set_module_info(struct snd_sof_widget *swidget) static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_ipc4_msg *msg) { struct sof_ipc4_fw_module *fw_module; + uint32_t type; int ret;
ret = sof_ipc4_widget_set_module_info(swidget); @@ -330,6 +331,9 @@ static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_ msg->extension = SOF_IPC4_MOD_EXT_PPL_ID(swidget->pipeline_id); msg->extension |= SOF_IPC4_MOD_EXT_CORE_ID(swidget->core);
+ type = fw_module->man4_module_entry.type & SOF_IPC4_MODULE_DP ? 1 : 0; + msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(type); + return 0; }
@@ -1532,8 +1536,6 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
msg->extension &= ~SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK; msg->extension |= ipc_size >> 2; - msg->extension &= ~SOF_IPC4_MOD_EXT_DOMAIN_MASK; - msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(pipeline->lp_mode); } dev_dbg(sdev->dev, "Create widget %s instance %d - pipe %d - core %d\n", swidget->widget->name, swidget->instance_id, swidget->pipeline_id, swidget->core); diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 56ab80e722ce..0aa87a8add5d 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -15,7 +15,18 @@ #define SOF_IPC4_FW_PAGE(x) ((((x) + BIT(12) - 1) & ~(BIT(12) - 1)) >> 12) #define SOF_IPC4_FW_ROUNDUP(x) (((x) + BIT(6) - 1) & (~(BIT(6) - 1)))
-#define SOF_IPC4_MODULE_LL BIT(5) +#define SOF_IPC4_MODULE_LOAD_TYPE GENMASK(3, 0) +#define SOF_IPC4_MODULE_AUTO_START BIT(4) +/* + * Two module schedule domains in fw : + * LL domain - Low latency domain + * DP domain - Data processing domain + * The LL setting should be equal to !DP setting + */ +#define SOF_IPC4_MODULE_LL BIT(5) +#define SOF_IPC4_MODULE_DP BIT(6) +#define SOF_IPC4_MODULE_LIB_CODE BIT(7) + #define SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE 12 #define SOF_IPC4_PIPELINE_OBJECT_SIZE 448 #define SOF_IPC4_DATA_QUEUE_OBJECT_SIZE 128
From: Peter Ujfalusi peter.ujfalusi@linux.intel.com
Print out the found extended manifest magic number in case it is not matching with the expected one (0x6e614d58) in debug level. It is fairly unlikely that the firmware does not have ext_man section and the found value in place of the magic number can help rootcausing boot related issues.
Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Signed-off-by: Peter Ujfalusi peter.ujfalusi@linux.intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/sof/ipc3-loader.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/sound/soc/sof/ipc3-loader.c b/sound/soc/sof/ipc3-loader.c index c573e7593808..bf423ca4e97b 100644 --- a/sound/soc/sof/ipc3-loader.c +++ b/sound/soc/sof/ipc3-loader.c @@ -109,7 +109,7 @@ static int ipc3_fw_ext_man_get_config_data(struct snd_sof_dev *sdev, return 0; }
-static ssize_t ipc3_fw_ext_man_size(const struct firmware *fw) +static ssize_t ipc3_fw_ext_man_size(struct snd_sof_dev *sdev, const struct firmware *fw) { const struct sof_ext_man_header *head;
@@ -131,6 +131,8 @@ static ssize_t ipc3_fw_ext_man_size(const struct firmware *fw) return head->full_size;
/* otherwise given fw don't have an extended manifest */ + dev_dbg(sdev->dev, "Unexpected extended manifest magic number: %#x\n", + head->magic); return 0; }
@@ -147,7 +149,7 @@ static size_t sof_ipc3_fw_parse_ext_man(struct snd_sof_dev *sdev)
head = (struct sof_ext_man_header *)fw->data; remaining = head->full_size - head->header_size; - ext_man_size = ipc3_fw_ext_man_size(fw); + ext_man_size = ipc3_fw_ext_man_size(sdev, fw);
/* Assert firmware starts with extended manifest */ if (ext_man_size <= 0)
From: Peter Ujfalusi peter.ujfalusi@linux.intel.com
fixup_tplg_name() doesn't need to keep the string, allocated for filename - it's temporary.
Inspired by similar change for hda: commit b9088535e102 ("ASoC: SOF: Intel: HDA: don't keep a temporary variable")
Reviewed-by: Bard Liao yung-chuan.liao@linux.intel.com Signed-off-by: Peter Ujfalusi peter.ujfalusi@linux.intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/sof/intel/atom.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/sound/soc/sof/intel/atom.c b/sound/soc/sof/intel/atom.c index ff5900b155dc..bd9789b483b1 100644 --- a/sound/soc/sof/intel/atom.c +++ b/sound/soc/sof/intel/atom.c @@ -274,22 +274,22 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev, const char *ssp_str) { const char *tplg_filename = NULL; - char *filename; - char *split_ext; + const char *split_ext; + char *filename, *tmp;
- filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL); + filename = kstrdup(sof_tplg_filename, GFP_KERNEL); if (!filename) return NULL;
/* this assumes a .tplg extension */ - split_ext = strsep(&filename, "."); - if (split_ext) { + tmp = filename; + split_ext = strsep(&tmp, "."); + if (split_ext) tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, "%s-%s.tplg", split_ext, ssp_str); - if (!tplg_filename) - return NULL; - } + kfree(filename); + return tplg_filename; }
The fw_filename is now set at a higher level and can be overridden by kernel parameters or DMI quirks.
Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Reviewed-by: Bard Liao yung-chuan.liao@linux.intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/sof/intel/hda.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index be3c4f1d8ff5..b702412e2a17 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1401,7 +1401,6 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev mach->mach_params.links = mach->links; mach->mach_params.link_mask = mach->link_mask; mach->mach_params.platform = dev_name(sdev->dev); - pdata->fw_filename = pdata->desc->default_fw_filename[pdata->ipc_type]; pdata->tplg_filename = mach->sof_tplg_filename;
/*
We do all kinds of renaming tricks that get in the way of kernel parameter and DMI quirk overrides at a higher level.
Tested on UpExtreme board with
options snd-sof-pci tplg_filename=sof-hda-generic.tplg
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Bard Liao yung-chuan.liao@linux.intel.com Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com --- sound/soc/sof/intel/hda.c | 70 +++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 22 deletions(-)
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index b702412e2a17..d337d55050e2 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -776,13 +776,12 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev, return tplg_filename; }
-static int dmic_topology_fixup(struct snd_sof_dev *sdev, - const char **tplg_filename, - const char *idisp_str, - int *dmic_found) +static int dmic_detect_topology_fixup(struct snd_sof_dev *sdev, + const char **tplg_filename, + const char *idisp_str, + int *dmic_found, + bool tplg_fixup) { - const char *default_tplg_filename = *tplg_filename; - const char *fixed_tplg_filename; const char *dmic_str; int dmic_num;
@@ -808,14 +807,19 @@ static int dmic_topology_fixup(struct snd_sof_dev *sdev, break; }
- fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename, - idisp_str, dmic_str); - if (!fixed_tplg_filename) - return -ENOMEM; + if (tplg_fixup) { + const char *default_tplg_filename = *tplg_filename; + const char *fixed_tplg_filename; + + fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename, + idisp_str, dmic_str); + if (!fixed_tplg_filename) + return -ENOMEM; + *tplg_filename = fixed_tplg_filename; + }
dev_info(sdev->dev, "DMICs detected in NHLT tables: %d\n", dmic_num); *dmic_found = dmic_num; - *tplg_filename = fixed_tplg_filename;
return 0; } @@ -1221,6 +1225,8 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev, * - one external HDAudio codec */ if (!*mach && codec_num <= 2) { + bool tplg_fixup; + hda_mach = snd_soc_acpi_intel_hda_machines;
dev_info(bus->dev, "using HDA machine driver %s now\n", @@ -1232,8 +1238,15 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev, idisp_str = "";
/* topology: use the info from hda_machines */ - tplg_filename = hda_mach->sof_tplg_filename; - ret = dmic_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num); + if (pdata->tplg_filename) { + tplg_fixup = false; + tplg_filename = pdata->tplg_filename; + } else { + tplg_fixup = true; + tplg_filename = hda_mach->sof_tplg_filename; + } + ret = dmic_detect_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num, + tplg_fixup); if (ret < 0) return;
@@ -1397,11 +1410,19 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev } if (mach && mach->link_mask) { int dmic_num = 0; + bool tplg_fixup; + const char *tplg_filename;
mach->mach_params.links = mach->links; mach->mach_params.link_mask = mach->link_mask; mach->mach_params.platform = dev_name(sdev->dev); - pdata->tplg_filename = mach->sof_tplg_filename; + + if (pdata->tplg_filename) { + tplg_fixup = false; + } else { + tplg_fixup = true; + tplg_filename = mach->sof_tplg_filename; + }
/* * DMICs use up to 4 pins and are typically pin-muxed with SoundWire @@ -1411,15 +1432,15 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev * b) the NHLT table reports the presence of microphones */ if (hweight_long(mach->link_mask) <= 2) { - const char *tplg_filename = mach->sof_tplg_filename; int ret;
- ret = dmic_topology_fixup(sdev, &tplg_filename, "", &dmic_num); + ret = dmic_detect_topology_fixup(sdev, &tplg_filename, "", + &dmic_num, tplg_fixup); if (ret < 0) return NULL; - - pdata->tplg_filename = tplg_filename; } + if (tplg_fixup) + pdata->tplg_filename = tplg_filename; mach->mach_params.dmic_num = dmic_num;
dev_dbg(sdev->dev, @@ -1465,18 +1486,22 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) mach = snd_soc_acpi_find_machine(desc->machines); if (mach) { bool add_extension = false; + bool tplg_fixup = false;
/* * If tplg file name is overridden, use it instead of * the one set in mach table */ - if (!sof_pdata->tplg_filename) + if (!sof_pdata->tplg_filename) { sof_pdata->tplg_filename = mach->sof_tplg_filename; + tplg_fixup = true; + }
/* report to machine driver if any DMICs are found */ mach->mach_params.dmic_num = check_dmic_num(sdev);
- if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER && + if (tplg_fixup && + mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER && mach->mach_params.dmic_num) { tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, "%s%s%d%s", @@ -1499,7 +1524,8 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) /* report SSP link mask to machine driver */ mach->mach_params.i2s_link_mask = check_nhlt_ssp_mask(sdev);
- if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER && + if (tplg_fixup && + mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER && mach->mach_params.i2s_link_mask) { int ssp_num;
@@ -1522,7 +1548,7 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) add_extension = true; }
- if (add_extension) { + if (tplg_fixup && add_extension) { tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, "%s%s", sof_pdata->tplg_filename,
assign/free are not well aligned to usual conventions and specifically not to the compressed ops that make use of the probe callbacks.
Use the more common startup/shutdown. No functional change beyond renaming.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Reviewed-by: Bard Liao yung-chuan.liao@linux.intel.com --- sound/soc/sof/intel/hda-probes.c | 16 ++++++++-------- sound/soc/sof/sof-client-probes.c | 8 ++++---- sound/soc/sof/sof-client-probes.h | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/sound/soc/sof/intel/hda-probes.c b/sound/soc/sof/intel/hda-probes.c index 31e85d4aae8c..56a533c63cb0 100644 --- a/sound/soc/sof/intel/hda-probes.c +++ b/sound/soc/sof/intel/hda-probes.c @@ -25,9 +25,9 @@ hda_compr_get_stream(struct snd_compr_stream *cstream) return cstream->runtime->private_data; }
-static int hda_probes_compr_assign(struct sof_client_dev *cdev, - struct snd_compr_stream *cstream, - struct snd_soc_dai *dai, u32 *stream_id) +static int hda_probes_compr_startup(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai, u32 *stream_id) { struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); struct hdac_ext_stream *hext_stream; @@ -45,9 +45,9 @@ static int hda_probes_compr_assign(struct sof_client_dev *cdev, return 0; }
-static int hda_probes_compr_free(struct sof_client_dev *cdev, - struct snd_compr_stream *cstream, - struct snd_soc_dai *dai) +static int hda_probes_compr_shutdown(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai) { struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream); struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); @@ -127,8 +127,8 @@ static int hda_probes_compr_pointer(struct sof_client_dev *cdev,
/* SOF client implementation */ static const struct sof_probes_host_ops hda_probes_ops = { - .assign = hda_probes_compr_assign, - .free = hda_probes_compr_free, + .startup = hda_probes_compr_startup, + .shutdown = hda_probes_compr_shutdown, .set_params = hda_probes_compr_set_params, .trigger = hda_probes_compr_trigger, .pointer = hda_probes_compr_pointer, diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c index e7e78d1a8ec3..eb246b823461 100644 --- a/sound/soc/sof/sof-client-probes.c +++ b/sound/soc/sof/sof-client-probes.c @@ -270,9 +270,9 @@ static int sof_probes_compr_startup(struct snd_compr_stream *cstream, if (ret) return ret;
- ret = ops->assign(cdev, cstream, dai, &priv->extractor_stream_tag); + ret = ops->startup(cdev, cstream, dai, &priv->extractor_stream_tag); if (ret) { - dev_err(dai->dev, "Failed to assign probe stream: %d\n", ret); + dev_err(dai->dev, "Failed to startup probe stream: %d\n", ret); priv->extractor_stream_tag = SOF_PROBES_INVALID_NODE_ID; sof_client_core_module_put(cdev); } @@ -310,7 +310,7 @@ static int sof_probes_compr_shutdown(struct snd_compr_stream *cstream, priv->extractor_stream_tag = SOF_PROBES_INVALID_NODE_ID; snd_compr_free_pages(cstream);
- ret = ops->free(cdev, cstream, dai); + ret = ops->shutdown(cdev, cstream, dai);
sof_client_core_module_put(cdev);
@@ -709,7 +709,7 @@ static int sof_probes_client_probe(struct auxiliary_device *auxdev,
ops = dev->platform_data;
- if (!ops->assign || !ops->free || !ops->set_params || !ops->trigger || + if (!ops->startup || !ops->shutdown || !ops->set_params || !ops->trigger || !ops->pointer) { dev_err(dev, "missing platform callback(s)\n"); return -ENODEV; diff --git a/sound/soc/sof/sof-client-probes.h b/sound/soc/sof/sof-client-probes.h index 0f9ed4569fd3..9e43f3c444f8 100644 --- a/sound/soc/sof/sof-client-probes.h +++ b/sound/soc/sof/sof-client-probes.h @@ -14,10 +14,10 @@ struct snd_soc_dai; * DSP and host, like HDA. */ struct sof_probes_host_ops { - int (*assign)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, - struct snd_soc_dai *dai, u32 *stream_id); - int (*free)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, - struct snd_soc_dai *dai); + int (*startup)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, + struct snd_soc_dai *dai, u32 *stream_id); + int (*shutdown)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, + struct snd_soc_dai *dai); int (*set_params)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, struct snd_compr_params *params, struct snd_soc_dai *dai);
We should be consistent and always test that the DMA buffer is allocated before continuing with the hw_params setup.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Reviewed-by: Bard Liao yung-chuan.liao@linux.intel.com --- sound/soc/sof/intel/hda-stream.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 4531e1ee5ed0..b58662faa4aa 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -411,6 +411,11 @@ int hda_dsp_iccmax_stream_hw_params(struct snd_sof_dev *sdev, struct hdac_ext_st return -ENODEV; }
+ if (!dmab) { + dev_err(sdev->dev, "error: no dma buffer allocated!\n"); + return -ENODEV; + } + if (hstream->posbuf) *hstream->posbuf = 0;
@@ -485,16 +490,16 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, return -ENODEV; }
- /* decouple host and link DMA */ - mask = 0x1 << hstream->index; - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - mask, mask); - if (!dmab) { dev_err(sdev->dev, "error: no dma buffer allocated!\n"); return -ENODEV; }
+ /* decouple host and link DMA */ + mask = 0x1 << hstream->index; + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, + mask, mask); + /* clear stream status */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, SOF_HDA_CL_DMA_SD_INT_MASK |
On Fri, 15 Jul 2022 09:52:05 -0500, Pierre-Louis Bossart wrote:
Set of updates for IPC3, IPC4, MTL support and cleanups for the topology filename override which was broken for HDaudio platforms.
It may be too late for 5.20, it's ok if these patches are applied in the next cycle.
The topology override depends on the patch "ASoC: SOF: Intel: enable dmic handling with 2 or fewer SoundWire links" shared in a separate patchset.
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[01/11] ASoC: SOF: Intel: MTL: remove redundant snd_sof_dsp_read() call commit: 740e5d8713e08607c280e1569374401461f3ed5b [02/11] ASoC: SOF: ipc4-topology: move ida allocate/free to widget_setup/free commit: 711d0427c7134c5ba65b8f408888a0335e23ed23 [03/11] ASoC: SOF: ipc4-pcm: set pcm rate to dai setting commit: bdb803c8280ba4fd8b8c1cf9cb69f3555853f397 [04/11] ASoC: SOF: add ipc4 SRC module support commit: b85f4fc40d56f69ee8e2ca99f202fb287bd767c9 [05/11] ASoC: SOF: ipc4-topology: set domain bit based on dp domain type commit: dc6137a56a7227da6e0d4cff6dfb952173403e71 [06/11] ASoC: SOF: ipc3-loader: Print out the non matching ext_man magic number commit: b9cb044f35fd5d6fdff92a0be23b020372525fef [07/11] ASoC: SOF: Intel: atom: don't keep a temporary string in fixup_tplg_name commit: 27b196c19c5a10abf1bf5a379c1a6154a1686ec4 [08/11] ASoC: SOF: Intel: hda: don't set fw_filename commit: ef05eb575ed98f32d380a6ac8ecdc865b0f4e146 [09/11] ASoC: SOF: Intel: hda: only fixup topology name if not set already commit: 054d1fd1380a88e64fadee38771e311184db544a [10/11] ASoC: SOF: probes: rename assign/free callbacks as startup/shutdown commit: bdcf7926fab202d37bfc8e17f1c8ed5d2e611404 [11/11] ASoC: SOF: Intel: hda-stream: test DMA buffer first in hw_params commit: 321add801bcd186c6b5477c0857521e127dbf016
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (2)
-
Mark Brown
-
Pierre-Louis Bossart