From fc85d9d0b3ba8f8934963c760af98fc38029d9da Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 9 Nov 2023 15:58:59 +0200 Subject: ASoC: SOF: imx8m: Add DAI driver entry for MICFIL PDM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow creating of PDM DAI links. Reviewed-by: Péter Ujfalusi Reviewed-by: Iuliana Prodan Signed-off-by: Daniel Baluta Link: https://lore.kernel.org/r/20231109135900.88310-2-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8m.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index 2680f061ba42..f088fd1a672b 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -313,6 +313,13 @@ static struct snd_soc_dai_driver imx8m_dai[] = { .channels_max = 32, }, }, +{ + .name = "micfil", + .capture = { + .channels_min = 1, + .channels_max = 8, + }, +}, }; static int imx8m_dsp_set_power_state(struct snd_sof_dev *sdev, -- cgit v1.2.3-59-g8ed1b From 89ef42088b3ba884a007ad10bd89ce8a81b9dedd Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 9 Nov 2023 15:59:00 +0200 Subject: ASoC: SOF: Add support for configuring PDM interface from topology MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we only support configuration for number of channels and sample rate. Reviewed-by: Péter Ujfalusi Reviewed-by: Iuliana Prodan Signed-off-by: Daniel Baluta Link: https://lore.kernel.org/r/20231109135900.88310-3-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- include/sound/sof/dai-imx.h | 7 +++++++ include/sound/sof/dai.h | 2 ++ include/uapi/sound/sof/tokens.h | 4 ++++ sound/soc/sof/ipc3-pcm.c | 11 ++++++++++ sound/soc/sof/ipc3-topology.c | 46 +++++++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-audio.h | 1 + sound/soc/sof/topology.c | 5 +++++ 7 files changed, 76 insertions(+) (limited to 'sound/soc/sof') diff --git a/include/sound/sof/dai-imx.h b/include/sound/sof/dai-imx.h index ca8325353d41..6bc987bd4761 100644 --- a/include/sound/sof/dai-imx.h +++ b/include/sound/sof/dai-imx.h @@ -51,4 +51,11 @@ struct sof_ipc_dai_sai_params { uint16_t tdm_slot_width; uint16_t reserved2; /* alignment */ } __packed; + +/* MICFIL Configuration Request - SOF_IPC_DAI_MICFIL_CONFIG */ +struct sof_ipc_dai_micfil_params { + uint32_t pdm_rate; + uint32_t pdm_ch; +} __packed; + #endif diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h index 3041f5805b7b..4773a5f616a4 100644 --- a/include/sound/sof/dai.h +++ b/include/sound/sof/dai.h @@ -88,6 +88,7 @@ enum sof_ipc_dai_type { SOF_DAI_AMD_HS, /**< Amd HS */ SOF_DAI_AMD_SP_VIRTUAL, /**< AMD ACP SP VIRTUAL */ SOF_DAI_AMD_HS_VIRTUAL, /**< AMD ACP HS VIRTUAL */ + SOF_DAI_IMX_MICFIL, /** < i.MX MICFIL PDM */ }; /* general purpose DAI configuration */ @@ -117,6 +118,7 @@ struct sof_ipc_dai_config { struct sof_ipc_dai_acpdmic_params acpdmic; struct sof_ipc_dai_acp_params acphs; struct sof_ipc_dai_mtk_afe_params afe; + struct sof_ipc_dai_micfil_params micfil; }; } __packed; diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 453cab2a1209..0fb39780f9bd 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -213,4 +213,8 @@ #define SOF_TKN_AMD_ACPI2S_CH 1701 #define SOF_TKN_AMD_ACPI2S_TDM_MODE 1702 +/* MICFIL PDM */ +#define SOF_TKN_IMX_MICFIL_RATE 2000 +#define SOF_TKN_IMX_MICFIL_CH 2001 + #endif diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index 2d0addcbc819..330f04bcd75d 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -384,6 +384,17 @@ static int sof_ipc3_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, dev_dbg(component->dev, "AMD_DMIC channels_min: %d channels_max: %d\n", channels->min, channels->max); break; + case SOF_DAI_IMX_MICFIL: + rate->min = private->dai_config->micfil.pdm_rate; + rate->max = private->dai_config->micfil.pdm_rate; + channels->min = private->dai_config->micfil.pdm_ch; + channels->max = private->dai_config->micfil.pdm_ch; + + dev_dbg(component->dev, + "MICFIL PDM rate_min: %d rate_max: %d\n", rate->min, rate->max); + dev_dbg(component->dev, "MICFIL PDM channels_min: %d channels_max: %d\n", + channels->min, channels->max); + break; default: dev_err(component->dev, "Invalid DAI type %d\n", private->dai_config->type); break; diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index ba4ef290b634..7a4932c152a9 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -286,6 +286,16 @@ static const struct sof_topology_token acpi2s_tokens[] = { offsetof(struct sof_ipc_dai_acp_params, tdm_mode)}, }; +/* MICFIL PDM */ +static const struct sof_topology_token micfil_pdm_tokens[] = { + {SOF_TKN_IMX_MICFIL_RATE, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_micfil_params, pdm_rate)}, + {SOF_TKN_IMX_MICFIL_CH, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_micfil_params, pdm_ch)}, +}; + /* Core tokens */ static const struct sof_topology_token core_tokens[] = { {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, @@ -322,6 +332,8 @@ static const struct sof_token_info ipc3_token_list[SOF_TOKEN_COUNT] = { [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)}, + [SOF_MICFIL_TOKENS] = {"MICFIL PDM tokens", + micfil_pdm_tokens, ARRAY_SIZE(micfil_pdm_tokens)}, }; /** @@ -1136,6 +1148,37 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, struct snd_sof_da return 0; } +static int sof_link_micfil_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, + struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) +{ + 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); + + config->hdr.size = size; + + /* parse the required set of MICFIL PDM tokens based on num_hw_cfgs */ + ret = sof_update_ipc_object(scomp, &config->micfil, SOF_MICFIL_TOKENS, slink->tuples, + slink->num_tuples, size, slink->num_hw_configs); + if (ret < 0) + return ret; + + dev_info(scomp->dev, "MICFIL PDM config dai_index %d channel %d rate %d\n", + config->dai_index, config->micfil.pdm_ch, config->micfil.pdm_rate); + + dai->number_configs = 1; + dai->current_config = 0; + private->dai_config = kmemdup(config, size, GFP_KERNEL); + if (!private->dai_config) + return -ENOMEM; + + return 0; +} + static int sof_link_acp_dmic_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) { @@ -1559,6 +1602,9 @@ static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget) case SOF_DAI_IMX_ESAI: ret = sof_link_esai_load(scomp, slink, config, dai); break; + case SOF_DAI_IMX_MICFIL: + ret = sof_link_micfil_load(scomp, slink, config, dai); + break; case SOF_DAI_AMD_BT: ret = sof_link_acp_bt_load(scomp, slink, config, dai); break; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 5d5eeb1a1a6f..99c940b22538 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -275,6 +275,7 @@ enum sof_tokens { SOF_GAIN_TOKENS, SOF_ACPDMIC_TOKENS, SOF_ACPI2S_TOKENS, + SOF_MICFIL_TOKENS, /* this should be the last */ SOF_TOKEN_COUNT, diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index a3a3af252259..9f717366cddc 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -296,6 +296,7 @@ static const struct sof_dai_types sof_dais[] = { {"AFE", SOF_DAI_MEDIATEK_AFE}, {"ACPSP_VIRTUAL", SOF_DAI_AMD_SP_VIRTUAL}, {"ACPHS_VIRTUAL", SOF_DAI_AMD_HS_VIRTUAL}, + {"MICFIL", SOF_DAI_IMX_MICFIL}, }; @@ -1960,6 +1961,10 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_ token_id = SOF_ACPI2S_TOKENS; num_tuples += token_list[SOF_ACPI2S_TOKENS].count; break; + case SOF_DAI_IMX_MICFIL: + token_id = SOF_MICFIL_TOKENS; + num_tuples += token_list[SOF_MICFIL_TOKENS].count; + break; default: break; } -- cgit v1.2.3-59-g8ed1b From ab475966455ce285c2c9978a3e3bfe97d75ff8d4 Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Fri, 3 Nov 2023 17:54:30 +0800 Subject: ASoC: SOF: mediatek: mt8195: clean up unused code Since there are some variables that are no longer being used, we remove the code that was implemented for those variables. Signed-off-by: Trevor Wu Reviewed-by: Yaochun Hung Reviewed-by: AngeloGioacchino Del Regno Tested-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20231103095433.10475-2-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/mt8195/mt8195.c | 49 ---------------------------------- 1 file changed, 49 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c index cac0a085f60a..8ee7ee246344 100644 --- a/sound/soc/sof/mediatek/mt8195/mt8195.c +++ b/sound/soc/sof/mediatek/mt8195/mt8195.c @@ -96,29 +96,6 @@ static int platform_parse_resource(struct platform_device *pdev, void *data) struct mtk_adsp_chip_info *adsp = data; int ret; - mem_region = of_parse_phandle(dev->of_node, "memory-region", 0); - if (!mem_region) { - dev_err(dev, "no dma memory-region phandle\n"); - return -ENODEV; - } - - ret = of_address_to_resource(mem_region, 0, &res); - of_node_put(mem_region); - if (ret) { - dev_err(dev, "of_address_to_resource dma failed\n"); - return ret; - } - - dev_dbg(dev, "DMA %pR\n", &res); - - adsp->pa_shared_dram = (phys_addr_t)res.start; - adsp->shared_size = resource_size(&res); - if (adsp->pa_shared_dram & DRAM_REMAP_MASK) { - dev_err(dev, "adsp shared dma memory(%#x) is not 4K-aligned\n", - (u32)adsp->pa_shared_dram); - return -EINVAL; - } - ret = of_reserved_mem_device_init(dev); if (ret) { dev_err(dev, "of_reserved_mem_device_init failed\n"); @@ -238,26 +215,6 @@ static int adsp_memory_remap_init(struct device *dev, struct mtk_adsp_chip_info return 0; } -static int adsp_shared_base_ioremap(struct platform_device *pdev, void *data) -{ - struct device *dev = &pdev->dev; - struct mtk_adsp_chip_info *adsp = data; - - /* remap shared-dram base to be non-cachable */ - adsp->shared_dram = devm_ioremap(dev, adsp->pa_shared_dram, - adsp->shared_size); - if (!adsp->shared_dram) { - dev_err(dev, "failed to ioremap base %pa size %#x\n", - adsp->shared_dram, adsp->shared_size); - return -ENOMEM; - } - - dev_dbg(dev, "shared-dram vbase=%p, phy addr :%pa, size=%#x\n", - adsp->shared_dram, &adsp->pa_shared_dram, adsp->shared_size); - - return 0; -} - static int mt8195_run(struct snd_sof_dev *sdev) { u32 adsp_bootup_addr; @@ -338,12 +295,6 @@ static int mt8195_dsp_probe(struct snd_sof_dev *sdev) } priv->adsp->va_dram = sdev->bar[SOF_FW_BLK_TYPE_SRAM]; - ret = adsp_shared_base_ioremap(pdev, priv->adsp); - if (ret) { - dev_err(sdev->dev, "adsp_shared_base_ioremap fail!\n"); - goto err_adsp_sram_power_off; - } - sdev->bar[DSP_REG_BAR] = priv->adsp->va_cfgreg; sdev->mmio_bar = SOF_FW_BLK_TYPE_SRAM; -- cgit v1.2.3-59-g8ed1b From a4de5a345cf76c6f294a906e11c2fb675a46fd3d Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Fri, 3 Nov 2023 17:54:31 +0800 Subject: ASoC: SOF: mediatek: mt8186: clean up unused code Since there are some variables that are no longer being used, we remove the code that was implemented for those variables. Signed-off-by: Trevor Wu Reviewed-by: Yaochun Hung Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20231103095433.10475-3-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/mt8186/mt8186.c | 49 ---------------------------------- 1 file changed, 49 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/mediatek/mt8186/mt8186.c b/sound/soc/sof/mediatek/mt8186/mt8186.c index b69fa788b16f..0d2d7d697de0 100644 --- a/sound/soc/sof/mediatek/mt8186/mt8186.c +++ b/sound/soc/sof/mediatek/mt8186/mt8186.c @@ -96,29 +96,6 @@ static int platform_parse_resource(struct platform_device *pdev, void *data) struct mtk_adsp_chip_info *adsp = data; int ret; - mem_region = of_parse_phandle(dev->of_node, "memory-region", 0); - if (!mem_region) { - dev_err(dev, "no dma memory-region phandle\n"); - return -ENODEV; - } - - ret = of_address_to_resource(mem_region, 0, &res); - of_node_put(mem_region); - if (ret) { - dev_err(dev, "of_address_to_resource dma failed\n"); - return ret; - } - - dev_dbg(dev, "DMA %pR\n", &res); - - adsp->pa_shared_dram = (phys_addr_t)res.start; - adsp->shared_size = resource_size(&res); - if (adsp->pa_shared_dram & DRAM_REMAP_MASK) { - dev_err(dev, "adsp shared dma memory(%#x) is not 4K-aligned\n", - (u32)adsp->pa_shared_dram); - return -EINVAL; - } - ret = of_reserved_mem_device_init(dev); if (ret) { dev_err(dev, "of_reserved_mem_device_init failed\n"); @@ -248,26 +225,6 @@ static int adsp_memory_remap_init(struct snd_sof_dev *sdev, struct mtk_adsp_chip return 0; } -static int adsp_shared_base_ioremap(struct platform_device *pdev, void *data) -{ - struct device *dev = &pdev->dev; - struct mtk_adsp_chip_info *adsp = data; - - /* remap shared-dram base to be non-cachable */ - adsp->shared_dram = devm_ioremap(dev, adsp->pa_shared_dram, - adsp->shared_size); - if (!adsp->shared_dram) { - dev_err(dev, "failed to ioremap base %pa size %#x\n", - adsp->shared_dram, adsp->shared_size); - return -ENOMEM; - } - - dev_dbg(dev, "shared-dram vbase=%p, phy addr :%pa, size=%#x\n", - adsp->shared_dram, &adsp->pa_shared_dram, adsp->shared_size); - - return 0; -} - static int mt8186_run(struct snd_sof_dev *sdev) { u32 adsp_bootup_addr; @@ -324,12 +281,6 @@ static int mt8186_dsp_probe(struct snd_sof_dev *sdev) priv->adsp->va_dram = sdev->bar[SOF_FW_BLK_TYPE_SRAM]; - ret = adsp_shared_base_ioremap(pdev, priv->adsp); - if (ret) { - dev_err(sdev->dev, "adsp_shared_base_ioremap fail!\n"); - return ret; - } - sdev->bar[DSP_REG_BAR] = priv->adsp->va_cfgreg; sdev->bar[DSP_SECREG_BAR] = priv->adsp->va_secreg; sdev->bar[DSP_BUSREG_BAR] = priv->adsp->va_busreg; -- cgit v1.2.3-59-g8ed1b From a08ee9d00e3120e2e77a3fc093ba29070a3979be Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Fri, 3 Nov 2023 17:54:32 +0800 Subject: ASoC: SOF: mediatek: remove unused variables To prevent confusion on the follow-up platform, it is necessary to remove any unused variables within the struct mtk_adsp_chip_info. Signed-off-by: Trevor Wu Reviewed-by: Yaochun Hung Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20231103095433.10475-4-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/adsp_helper.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/mediatek/adsp_helper.h b/sound/soc/sof/mediatek/adsp_helper.h index d41e904e6614..35527567962e 100644 --- a/sound/soc/sof/mediatek/adsp_helper.h +++ b/sound/soc/sof/mediatek/adsp_helper.h @@ -15,17 +15,13 @@ struct mtk_adsp_chip_info { phys_addr_t pa_sram; phys_addr_t pa_dram; /* adsp dram physical base */ - phys_addr_t pa_shared_dram; /* adsp dram physical base */ phys_addr_t pa_cfgreg; u32 sramsize; u32 dramsize; u32 cfgregsize; - u32 shared_size; void __iomem *va_sram; /* corresponding to pa_sram */ void __iomem *va_dram; /* corresponding to pa_dram */ void __iomem *va_cfgreg; - void __iomem *shared_sram; /* part of va_sram */ - void __iomem *shared_dram; /* part of va_dram */ phys_addr_t adsp_bootup_addr; int dram_offset; /*dram offset between system and dsp view*/ -- cgit v1.2.3-59-g8ed1b From 5980bda0a998a6ee6afd83b97a482a40c1c68076 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 24 Nov 2023 17:08:50 +0200 Subject: ASoC: SOF: ipc4-topology: Helper to find an swidget by module/instance id The sof_ipc4_find_swidget_by_ids() can be used to find the swidget of a module instance. The lookup parameters are the module_id and the instance_id. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20231124150853.18648-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-priv.h | 3 +++ sound/soc/sof/ipc4-topology.c | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h index 9e69b7c29117..fea93b693f4d 100644 --- a/sound/soc/sof/ipc4-priv.h +++ b/sound/soc/sof/ipc4-priv.h @@ -115,6 +115,9 @@ int sof_ipc4_reload_fw_libraries(struct snd_sof_dev *sdev); struct sof_ipc4_fw_module *sof_ipc4_find_module_by_uuid(struct snd_sof_dev *sdev, const guid_t *uuid); +struct snd_sof_widget *sof_ipc4_find_swidget_by_ids(struct snd_sof_dev *sdev, + u32 module_id, int instance_id); + struct sof_ipc4_base_module_cfg; void sof_ipc4_update_cpc_from_manifest(struct snd_sof_dev *sdev, struct sof_ipc4_fw_module *fw_module, diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index b24a64377f68..8ab9c42069ee 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -167,6 +167,26 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { [SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)}, }; +struct snd_sof_widget *sof_ipc4_find_swidget_by_ids(struct snd_sof_dev *sdev, + u32 module_id, int instance_id) +{ + struct snd_sof_widget *swidget; + + list_for_each_entry(swidget, &sdev->widget_list, list) { + struct sof_ipc4_fw_module *fw_module = swidget->module_info; + + /* Only active module instances have valid instance_id */ + if (!swidget->use_count) + continue; + + if (fw_module && fw_module->man4_module_entry.id == module_id && + swidget->instance_id == instance_id) + return swidget; + } + + return NULL; +} + static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_format *pin_fmt, int num_formats) { -- cgit v1.2.3-59-g8ed1b From f5eb9945cf9c17eb016aa64c7de13875f259ea07 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 24 Nov 2023 17:08:52 +0200 Subject: ASoC: SOF: ipc4-control: Implement control update for switch/enum controls Implement the sof_ipc_tplg_control_ops.update function to support a control change notification from the firmware on switch or enum control types. Based on the module notification message content, look up the swidget, then the scontrol which was the source of the notification then if the message contains the changed values update the cached values. If only a notification without values received, marked the control as dirty and on next read access fetch the new values from the firmware. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20231124150853.18648-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-control.c | 179 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index 938efaceb81c..3d2a35f27a87 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -240,6 +240,50 @@ sof_ipc4_set_generic_control_data(struct snd_sof_dev *sdev, return ret; } +static void sof_ipc4_refresh_generic_control(struct snd_sof_control *scontrol) +{ + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct sof_ipc4_control_msg_payload *data; + struct sof_ipc4_msg *msg = &cdata->msg; + size_t data_size; + unsigned int i; + int ret; + + if (!scontrol->comp_data_dirty) + return; + + if (!pm_runtime_active(scomp->dev)) + return; + + data_size = struct_size(data, chanv, scontrol->num_channels); + data = kmalloc(data_size, GFP_KERNEL); + if (!data) + return; + + data->id = cdata->index; + data->num_elems = scontrol->num_channels; + msg->data_ptr = data; + msg->data_size = data_size; + + scontrol->comp_data_dirty = false; + ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, true); + msg->data_ptr = NULL; + msg->data_size = 0; + if (!ret) { + for (i = 0; i < scontrol->num_channels; i++) { + cdata->chanv[i].channel = data->chanv[i].channel; + cdata->chanv[i].value = data->chanv[i].value; + } + } else { + dev_err(scomp->dev, "Failed to read control data for %s\n", + scontrol->name); + scontrol->comp_data_dirty = true; + } + + kfree(data); +} + static bool sof_ipc4_switch_put(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol) { @@ -290,6 +334,8 @@ static int sof_ipc4_switch_get(struct snd_sof_control *scontrol, struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; unsigned int i; + sof_ipc4_refresh_generic_control(scontrol); + /* read back each channel */ for (i = 0; i < scontrol->num_channels; i++) ucontrol->value.integer.value[i] = cdata->chanv[i].value; @@ -347,6 +393,8 @@ static int sof_ipc4_enum_get(struct snd_sof_control *scontrol, struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; unsigned int i; + sof_ipc4_refresh_generic_control(scontrol); + /* read back each channel */ for (i = 0; i < scontrol->num_channels; i++) ucontrol->value.enumerated.item[i] = cdata->chanv[i].value; @@ -601,6 +649,136 @@ sof_ipc4_volsw_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, return sof_ipc4_set_volume_data(sdev, swidget, scontrol, false); } +#define PARAM_ID_FROM_EXTENSION(_ext) (((_ext) & SOF_IPC4_MOD_EXT_MSG_PARAM_ID_MASK) \ + >> SOF_IPC4_MOD_EXT_MSG_PARAM_ID_SHIFT) + +static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message) +{ + struct sof_ipc4_msg *ipc4_msg = ipc_message; + struct sof_ipc4_notify_module_data *ndata = ipc4_msg->data_ptr; + struct sof_ipc4_control_msg_payload *msg_data; + struct sof_ipc4_control_data *cdata; + struct snd_soc_dapm_widget *widget; + struct snd_sof_control *scontrol; + struct snd_sof_widget *swidget; + struct snd_kcontrol *kc = NULL; + bool scontrol_found = false; + u32 event_param_id; + int i, type; + + if (ndata->event_data_size < sizeof(*msg_data)) { + dev_err(sdev->dev, + "%s: Invalid event data size for module %u.%u: %u\n", + __func__, ndata->module_id, ndata->instance_id, + ndata->event_data_size); + return; + } + + event_param_id = ndata->event_id & SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_PARAMID_MASK; + switch (event_param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + type = SND_SOC_TPLG_TYPE_MIXER; + break; + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + type = SND_SOC_TPLG_TYPE_ENUM; + break; + default: + dev_err(sdev->dev, + "%s: Invalid control type for module %u.%u: %u\n", + __func__, ndata->module_id, ndata->instance_id, + event_param_id); + return; + } + + /* Find the swidget based on ndata->module_id and ndata->instance_id */ + swidget = sof_ipc4_find_swidget_by_ids(sdev, ndata->module_id, + ndata->instance_id); + if (!swidget) { + dev_err(sdev->dev, "%s: Failed to find widget for module %u.%u\n", + __func__, ndata->module_id, ndata->instance_id); + return; + } + + /* Find the scontrol which is the source of the notification */ + msg_data = (struct sof_ipc4_control_msg_payload *)ndata->event_data; + list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { + if (scontrol->comp_id == swidget->comp_id) { + u32 local_param_id; + + cdata = scontrol->ipc_control_data; + /* + * The scontrol's param_id is stored in the IPC message + * template's extension + */ + local_param_id = PARAM_ID_FROM_EXTENSION(cdata->msg.extension); + if (local_param_id == event_param_id && + msg_data->id == cdata->index) { + scontrol_found = true; + break; + } + } + } + + if (!scontrol_found) { + dev_err(sdev->dev, + "%s: Failed to find control on widget %s: %u:%u\n", + __func__, swidget->widget->name, ndata->event_id & 0xffff, + msg_data->id); + return; + } + + if (msg_data->num_elems) { + /* + * The message includes the updated value/data, update the + * control's local cache using the received notification + */ + for (i = 0; i < msg_data->num_elems; i++) { + u32 channel = msg_data->chanv[i].channel; + + if (channel >= scontrol->num_channels) { + dev_warn(sdev->dev, + "Invalid channel index for %s: %u\n", + scontrol->name, i); + + /* + * Mark the scontrol as dirty to force a refresh + * on next read + */ + scontrol->comp_data_dirty = true; + break; + } + + cdata->chanv[channel].value = msg_data->chanv[i].value; + } + } else { + /* + * Mark the scontrol as dirty because the value/data is changed + * in firmware, forcing a refresh on next read access + */ + scontrol->comp_data_dirty = true; + } + + /* + * Look up the ALSA kcontrol of the scontrol to be able to send a + * notification to user space + */ + widget = swidget->widget; + for (i = 0; i < widget->num_kcontrols; i++) { + /* skip non matching types or non matching indexes within type */ + if (widget->dobj.widget.kcontrol_type[i] == type && + widget->kcontrol_news[i].index == cdata->index) { + kc = widget->kcontrols[i]; + break; + } + } + + if (!kc) + return; + + snd_ctl_notify_one(swidget->scomp->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, kc, 0); +} + /* set up all controls for the widget */ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { @@ -674,6 +852,7 @@ const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops = { .bytes_ext_put = sof_ipc4_bytes_ext_put, .bytes_ext_get = sof_ipc4_bytes_ext_get, .bytes_ext_volatile_get = sof_ipc4_bytes_ext_volatile_get, + .update = sof_ipc4_control_update, .widget_kcontrol_setup = sof_ipc4_widget_kcontrol_setup, .set_up_volume_table = sof_ipc4_set_up_volume_table, }; -- cgit v1.2.3-59-g8ed1b From 0ff23d460718641c80c8054425256391dca1ac7d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 24 Nov 2023 17:08:53 +0200 Subject: ASoC: SOF: ipc4: Handle ALSA kcontrol change notification from firmware The control change notification is sent as module notification with a standardized event_id (higher 16 bit is 0xA15A). Add generic code to handle the module notification and invoke the control update callback if the notification is an ALSA kcontrol change message. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20231124150853.18648-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index 8441f4ae4065..a9d9800d2fcc 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -78,6 +78,9 @@ static const struct sof_ipc4_fw_status { {165, "Reserved (ADSP_IPC_PIPELINE_ALREADY_EXISTS removed)"}, }; +typedef void (*ipc4_notification_handler)(struct snd_sof_dev *sdev, + struct sof_ipc4_msg *msg); + static int sof_ipc4_check_reply_status(struct snd_sof_dev *sdev, u32 status) { int i, ret; @@ -610,9 +613,55 @@ static int ipc4_fw_ready(struct snd_sof_dev *sdev, struct sof_ipc4_msg *ipc4_msg return sof_ipc4_init_msg_memory(sdev); } +static void sof_ipc4_module_notification_handler(struct snd_sof_dev *sdev, + struct sof_ipc4_msg *ipc4_msg) +{ + struct sof_ipc4_notify_module_data *data = ipc4_msg->data_ptr; + + /* + * If the notification includes additional, module specific data, then + * we need to re-allocate the buffer and re-read the whole payload, + * including the event_data + */ + if (data->event_data_size) { + void *new; + int ret; + + ipc4_msg->data_size += data->event_data_size; + + new = krealloc(ipc4_msg->data_ptr, ipc4_msg->data_size, GFP_KERNEL); + if (!new) { + ipc4_msg->data_size -= data->event_data_size; + return; + } + + /* re-read the whole payload */ + ipc4_msg->data_ptr = new; + ret = snd_sof_ipc_msg_data(sdev, NULL, ipc4_msg->data_ptr, + ipc4_msg->data_size); + if (ret < 0) { + dev_err(sdev->dev, + "Failed to read the full module notification: %d\n", + ret); + return; + } + data = ipc4_msg->data_ptr; + } + + /* Handle ALSA kcontrol notification */ + if ((data->event_id & SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_MASK) == + SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL) { + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + + if (tplg_ops->control->update) + tplg_ops->control->update(sdev, ipc4_msg); + } +} + static void sof_ipc4_rx_msg(struct snd_sof_dev *sdev) { struct sof_ipc4_msg *ipc4_msg = sdev->ipc->msg.rx_data; + ipc4_notification_handler handler_func = NULL; size_t data_size = 0; int err; @@ -648,6 +697,10 @@ static void sof_ipc4_rx_msg(struct snd_sof_dev *sdev) case SOF_IPC4_NOTIFY_EXCEPTION_CAUGHT: snd_sof_dsp_panic(sdev, 0, true); break; + case SOF_IPC4_NOTIFY_MODULE_NOTIFICATION: + data_size = sizeof(struct sof_ipc4_notify_module_data); + handler_func = sof_ipc4_module_notification_handler; + break; default: dev_dbg(sdev->dev, "Unhandled DSP message: %#x|%#x\n", ipc4_msg->primary, ipc4_msg->extension); @@ -663,6 +716,10 @@ static void sof_ipc4_rx_msg(struct snd_sof_dev *sdev) snd_sof_ipc_msg_data(sdev, NULL, ipc4_msg->data_ptr, ipc4_msg->data_size); } + /* Handle notifications with payload */ + if (handler_func) + handler_func(sdev, ipc4_msg); + sof_ipc4_log_header(sdev->dev, "ipc rx done ", ipc4_msg, true); if (data_size) { -- cgit v1.2.3-59-g8ed1b From d5070d0c10326e09276c34568b9a19fb9a727b6e Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Mon, 27 Nov 2023 12:52:35 +0200 Subject: ASoC: SOF: Intel: mtl: call dsp dump when boot retry fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call snd_sof_dsp_dbg_dump() with the same flags/dump_msg as used in function hda_loader.c/cl_dsp_init(). Reviewed-by: Péter Ujfalusi Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20231127105235.30071-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 254dbbeac1d0..3ef9e5c37028 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -440,7 +440,8 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; unsigned int status; - u32 ipc_hdr; + u32 ipc_hdr, flags; + char *dump_msg; int ret; /* step 1: purge FW request */ @@ -493,8 +494,18 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) return 0; err: - snd_sof_dsp_dbg_dump(sdev, "MTL DSP init fail", 0); + flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX | SOF_DBG_DUMP_OPTIONAL; + + /* after max boot attempts make sure that the dump is printed */ + if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) + flags &= ~SOF_DBG_DUMP_OPTIONAL; + + dump_msg = kasprintf(GFP_KERNEL, "Boot iteration failed: %d/%d", + hda->boot_iteration, HDA_FW_BOOT_ATTEMPTS); + snd_sof_dsp_dbg_dump(sdev, dump_msg, flags); mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE); + + kfree(dump_msg); return ret; } -- cgit v1.2.3-59-g8ed1b From 9b3cd8ebb19edd92300932b68fd6941eaf1852d0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 27 Nov 2023 12:43:13 +0200 Subject: ASoC: SOF: Intel: Use existing helpers to change GPROCEN and PIE bits Instead of directly changing the GPROCEN/PIE bits in PPCTL we should use the existing helper hda_dsp_ctrl_ppcap_enable() and hda_dsp_ctrl_ppcap_int_enable() helpers for clarity. Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20231127104313.16661-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 5 ++--- sound/soc/sof/intel/hda.c | 6 ++---- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 46fb2d1425e9..1805cf754beb 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -510,9 +510,8 @@ cleanup: return chip_info->init_core_mask; /* disable DSP */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, - SOF_HDA_REG_PP_PPCTL, - SOF_HDA_PPCTL_GPROCEN, 0); + hda_dsp_ctrl_ppcap_enable(sdev, false); + return ret; } diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 744c0dd5766d..fe4ae349dad5 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1350,8 +1350,7 @@ void hda_dsp_remove(struct snd_sof_dev *sdev) if (!sdev->dspless_mode_selected) { /* disable DSP IRQ */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - SOF_HDA_PPCTL_PIE, 0); + hda_dsp_ctrl_ppcap_int_enable(sdev, false); } /* disable CIE and GIE interrupts */ @@ -1366,8 +1365,7 @@ void hda_dsp_remove(struct snd_sof_dev *sdev) chip->power_down_dsp(sdev); /* disable DSP */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - SOF_HDA_PPCTL_GPROCEN, 0); + hda_dsp_ctrl_ppcap_enable(sdev, false); skip_disable_dsp: free_irq(sdev->ipc_irq, sdev); -- cgit v1.2.3-59-g8ed1b From 8c91ca76f44804868d12aed20ebdbc2f89aa7d60 Mon Sep 17 00:00:00 2001 From: Kamil Duljas Date: Thu, 16 Nov 2023 23:01:03 +0100 Subject: ASoC: SOF: icp3-dtrace: Fix wrong kfree() usage trace_filter_parse() allocs memory for *out and when -ENOMEM is returned, caller function, dfsentry_trace_filter_write() trying to freed this memory. After this patch, the memory is freed in trace_filter_parse() before -EINVAL returned. In caller function removed kfree(elms) from error label Signed-off-by: Kamil Duljas Link: https://lore.kernel.org/r/20231116220102.2097-2-kamil.duljas@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-dtrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ipc3-dtrace.c b/sound/soc/sof/ipc3-dtrace.c index 0dca139322f3..93b189c2d2ee 100644 --- a/sound/soc/sof/ipc3-dtrace.c +++ b/sound/soc/sof/ipc3-dtrace.c @@ -137,6 +137,7 @@ static int trace_filter_parse(struct snd_sof_dev *sdev, char *string, dev_err(sdev->dev, "Parsing filter entry '%s' failed with %d\n", entry, entry_len); + kfree(*out); return -EINVAL; } } @@ -208,13 +209,13 @@ static ssize_t dfsentry_trace_filter_write(struct file *file, const char __user ret = ipc3_trace_update_filter(sdev, num_elems, elems); if (ret < 0) { dev_err(sdev->dev, "Filter update failed: %d\n", ret); + kfree(elems); goto error; } } ret = count; error: kfree(string); - kfree(elems); return ret; } -- cgit v1.2.3-59-g8ed1b From 014fdeb0d747304111cfecf93df4407c1a0c80db Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:15 +0200 Subject: ASoC: SOF: Move sof_of_machine_select() to sof-of-dev.c from sof-audio.c Move the sof_of_machine_select() function to sof-of-dev.c file and provide an inline stub in case of non OF builds. Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 22 ---------------------- sound/soc/sof/sof-of-dev.c | 23 +++++++++++++++++++++++ sound/soc/sof/sof-of-dev.h | 9 +++++++++ 3 files changed, 32 insertions(+), 22 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 563fe6f7789f..2198bb8e92c3 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -990,28 +990,6 @@ int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd) } EXPORT_SYMBOL(sof_dai_get_bclk); -static struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev) -{ - struct snd_sof_pdata *sof_pdata = sdev->pdata; - const struct sof_dev_desc *desc = sof_pdata->desc; - struct snd_sof_of_mach *mach = desc->of_machines; - - if (!mach) - return NULL; - - for (; mach->compatible; mach++) { - if (of_machine_is_compatible(mach->compatible)) { - sof_pdata->tplg_filename = mach->sof_tplg_filename; - if (mach->fw_filename) - sof_pdata->fw_filename = mach->fw_filename; - - return mach; - } - } - - return NULL; -} - /* * SOF Driver enumeration. */ diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index c6be8a91e74b..432b511bf8c4 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -41,6 +41,29 @@ static void sof_of_probe_complete(struct device *dev) pm_runtime_enable(dev); } +struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *sof_pdata = sdev->pdata; + const struct sof_dev_desc *desc = sof_pdata->desc; + struct snd_sof_of_mach *mach = desc->of_machines; + + if (!mach) + return NULL; + + for (; mach->compatible; mach++) { + if (of_machine_is_compatible(mach->compatible)) { + sof_pdata->tplg_filename = mach->sof_tplg_filename; + if (mach->fw_filename) + sof_pdata->fw_filename = mach->fw_filename; + + return mach; + } + } + + return NULL; +} +EXPORT_SYMBOL(sof_of_machine_select); + int sof_of_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; diff --git a/sound/soc/sof/sof-of-dev.h b/sound/soc/sof/sof-of-dev.h index b6cc70595f3b..547e358a37e3 100644 --- a/sound/soc/sof/sof-of-dev.h +++ b/sound/soc/sof/sof-of-dev.h @@ -16,6 +16,15 @@ struct snd_sof_of_mach { const char *sof_tplg_filename; }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_OF_DEV) +struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev); +#else +static inline struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev) +{ + return NULL; +} +#endif + extern const struct dev_pm_ops sof_of_pm; int sof_of_probe(struct platform_device *pdev); -- cgit v1.2.3-59-g8ed1b From 3bc3477915587440035f192c89a1bf9a4360abb3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:16 +0200 Subject: ASoC: SOF: Move sof_machine_* functions from sof-audio.c to core.c Relocate the machine handling functions from sof-audio.c to core.c to maintain code separation. While doing the move, drop the redundant IS_ERR_OR_NULL(plat_data->pdev_mach) check from sof_machine_unregister() Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-audio.c | 98 ----------------------------------------------- sound/soc/sof/sof-priv.h | 2 - 3 files changed, 95 insertions(+), 100 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index d7b090224f1b..a87522ea4301 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -13,6 +13,7 @@ #include #include #include "sof-priv.h" +#include "sof-of-dev.h" #include "ops.h" #define CREATE_TRACE_POINTS @@ -143,6 +144,66 @@ void sof_set_fw_state(struct snd_sof_dev *sdev, enum sof_fw_state new_state) } EXPORT_SYMBOL(sof_set_fw_state); +/* SOF Driver enumeration */ +static int sof_machine_check(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *sof_pdata = sdev->pdata; + const struct sof_dev_desc *desc = sof_pdata->desc; + struct snd_soc_acpi_mach *mach; + + if (!IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)) { + const struct snd_sof_of_mach *of_mach; + + if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) && + sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC)) + goto nocodec; + + /* find machine */ + mach = snd_sof_machine_select(sdev); + if (mach) { + sof_pdata->machine = mach; + + if (sof_pdata->subsystem_id_set) { + mach->mach_params.subsystem_vendor = sof_pdata->subsystem_vendor; + mach->mach_params.subsystem_device = sof_pdata->subsystem_device; + mach->mach_params.subsystem_id_set = true; + } + + snd_sof_set_mach_params(mach, sdev); + return 0; + } + + of_mach = sof_of_machine_select(sdev); + if (of_mach) { + sof_pdata->of_machine = of_mach; + return 0; + } + + if (!IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)) { + dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); + return -ENODEV; + } + } else { + dev_warn(sdev->dev, "Force to use nocodec mode\n"); + } + +nocodec: + /* select nocodec mode */ + dev_warn(sdev->dev, "Using nocodec machine driver\n"); + mach = devm_kzalloc(sdev->dev, sizeof(*mach), GFP_KERNEL); + if (!mach) + return -ENOMEM; + + mach->drv_name = "sof-nocodec"; + if (!sof_pdata->tplg_filename) + sof_pdata->tplg_filename = desc->nocodec_tplg_filename; + + sof_pdata->machine = mach; + snd_sof_set_mach_params(mach, sdev); + + return 0; +} + /* * FW Boot State Transition Diagram * @@ -527,6 +588,40 @@ int snd_sof_device_shutdown(struct device *dev) } EXPORT_SYMBOL(snd_sof_device_shutdown); +/* Machine driver registering and unregistering */ +int sof_machine_register(struct snd_sof_dev *sdev, void *pdata) +{ + struct snd_sof_pdata *plat_data = pdata; + const char *drv_name; + const void *mach; + int size; + + drv_name = plat_data->machine->drv_name; + mach = plat_data->machine; + size = sizeof(*plat_data->machine); + + /* register machine driver, pass machine info as pdata */ + plat_data->pdev_mach = + platform_device_register_data(sdev->dev, drv_name, + PLATFORM_DEVID_NONE, mach, size); + if (IS_ERR(plat_data->pdev_mach)) + return PTR_ERR(plat_data->pdev_mach); + + dev_dbg(sdev->dev, "created machine %s\n", + dev_name(&plat_data->pdev_mach->dev)); + + return 0; +} +EXPORT_SYMBOL(sof_machine_register); + +void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata) +{ + struct snd_sof_pdata *plat_data = pdata; + + platform_device_unregister(plat_data->pdev_mach); +} +EXPORT_SYMBOL(sof_machine_unregister); + MODULE_AUTHOR("Liam Girdwood"); MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 2198bb8e92c3..de40a5e227f4 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -11,7 +11,6 @@ #include #include #include "sof-audio.h" -#include "sof-of-dev.h" #include "ops.h" static bool is_virtual_widget(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, @@ -989,100 +988,3 @@ int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd) return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_BCLK); } EXPORT_SYMBOL(sof_dai_get_bclk); - -/* - * SOF Driver enumeration. - */ -int sof_machine_check(struct snd_sof_dev *sdev) -{ - struct snd_sof_pdata *sof_pdata = sdev->pdata; - const struct sof_dev_desc *desc = sof_pdata->desc; - struct snd_soc_acpi_mach *mach; - - if (!IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)) { - const struct snd_sof_of_mach *of_mach; - - if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) && - sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC)) - goto nocodec; - - /* find machine */ - mach = snd_sof_machine_select(sdev); - if (mach) { - sof_pdata->machine = mach; - - if (sof_pdata->subsystem_id_set) { - mach->mach_params.subsystem_vendor = sof_pdata->subsystem_vendor; - mach->mach_params.subsystem_device = sof_pdata->subsystem_device; - mach->mach_params.subsystem_id_set = true; - } - - snd_sof_set_mach_params(mach, sdev); - return 0; - } - - of_mach = sof_of_machine_select(sdev); - if (of_mach) { - sof_pdata->of_machine = of_mach; - return 0; - } - - if (!IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)) { - dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); - return -ENODEV; - } - } else { - dev_warn(sdev->dev, "Force to use nocodec mode\n"); - } - -nocodec: - /* select nocodec mode */ - dev_warn(sdev->dev, "Using nocodec machine driver\n"); - mach = devm_kzalloc(sdev->dev, sizeof(*mach), GFP_KERNEL); - if (!mach) - return -ENOMEM; - - mach->drv_name = "sof-nocodec"; - if (!sof_pdata->tplg_filename) - sof_pdata->tplg_filename = desc->nocodec_tplg_filename; - - sof_pdata->machine = mach; - snd_sof_set_mach_params(mach, sdev); - - return 0; -} -EXPORT_SYMBOL(sof_machine_check); - -int sof_machine_register(struct snd_sof_dev *sdev, void *pdata) -{ - struct snd_sof_pdata *plat_data = pdata; - const char *drv_name; - const void *mach; - int size; - - drv_name = plat_data->machine->drv_name; - mach = plat_data->machine; - size = sizeof(*plat_data->machine); - - /* register machine driver, pass machine info as pdata */ - plat_data->pdev_mach = - platform_device_register_data(sdev->dev, drv_name, - PLATFORM_DEVID_NONE, mach, size); - if (IS_ERR(plat_data->pdev_mach)) - return PTR_ERR(plat_data->pdev_mach); - - dev_dbg(sdev->dev, "created machine %s\n", - dev_name(&plat_data->pdev_mach->dev)); - - return 0; -} -EXPORT_SYMBOL(sof_machine_register); - -void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata) -{ - struct snd_sof_pdata *plat_data = pdata; - - if (!IS_ERR_OR_NULL(plat_data->pdev_mach)) - platform_device_unregister(plat_data->pdev_mach); -} -EXPORT_SYMBOL(sof_machine_unregister); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index f4185012eb69..faa8a19ed737 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -814,8 +814,6 @@ int sof_stream_pcm_open(struct snd_sof_dev *sdev, int sof_stream_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); -int sof_machine_check(struct snd_sof_dev *sdev); - /* SOF client support */ #if IS_ENABLED(CONFIG_SND_SOC_SOF_CLIENT) int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id, -- cgit v1.2.3-59-g8ed1b From a07625dcaf994ab3c5a6a456624719df05ed8ad6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:18 +0200 Subject: ASoC: SOF: sof-acpi-dev: Save the default IPC type and path overrides Store the default IPC type and the firmware and topology path overrides to ipc_file_profile_base Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-acpi-dev.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 84a4a0a3318e..87c0c2edc4c9 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -87,6 +87,10 @@ int sof_acpi_probe(struct platform_device *pdev, const struct sof_dev_desc *desc else sof_pdata->tplg_filename_prefix = desc->default_tplg_path[SOF_IPC_TYPE_3]; + sof_pdata->ipc_file_profile_base.ipc_type = desc->ipc_default; + sof_pdata->ipc_file_profile_base.fw_path = fw_path; + sof_pdata->ipc_file_profile_base.tplg_path = tplg_path; + /* set callback to be called on successful device probe to enable runtime_pm */ sof_pdata->sof_probe_complete = sof_acpi_probe_complete; -- cgit v1.2.3-59-g8ed1b From 396016d56da4ad30fe9ff736e44d9e1457484805 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:19 +0200 Subject: ASoC: SOF: sof-of-dev: Save the default IPC type and path overrides Store the default IPC type and the firmware and topology path overrides to ipc_file_profile_base Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-of-dev.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index 432b511bf8c4..7b58f45790f7 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -99,6 +99,10 @@ int sof_of_probe(struct platform_device *pdev) else sof_pdata->tplg_filename_prefix = desc->default_tplg_path[SOF_IPC_TYPE_3]; + sof_pdata->ipc_file_profile_base.ipc_type = desc->ipc_default; + sof_pdata->ipc_file_profile_base.fw_path = fw_path; + sof_pdata->ipc_file_profile_base.tplg_path = tplg_path; + /* set callback to be called on successful device probe to enable runtime_pm */ sof_pdata->sof_probe_complete = sof_of_probe_complete; -- cgit v1.2.3-59-g8ed1b From 59ddeae037b81303063bcf62b70fb33841b3f89e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:20 +0200 Subject: ASoC: SOF: sof-pci-dev: Save the default IPC type and path overrides Store the default IPC type and the overrides to ipc_file_profile_base Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 64b326e3ef85..becc85b27d51 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -190,6 +190,7 @@ static void sof_pci_probe_complete(struct device *dev) int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { + struct sof_loadable_file_profile *path_override; struct device *dev = &pci->dev; const struct sof_dev_desc *desc = (const struct sof_dev_desc *)pci_id->driver_data; @@ -334,6 +335,20 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) sof_pdata->tplg_filename = sof_dmi_override_tplg_name; } + path_override = &sof_pdata->ipc_file_profile_base; + path_override->ipc_type = sof_pdata->ipc_type; + path_override->fw_path = fw_path; + path_override->fw_name = fw_filename; + path_override->fw_lib_path = lib_path; + path_override->tplg_path = tplg_path; + path_override->tplg_name = sof_pdata->tplg_filename; + + if (dmi_check_system(community_key_platforms) && + sof_dmi_use_community_key) { + path_override->fw_path_postfix = "community"; + path_override->fw_lib_path_postfix = "community"; + } + /* set callback to be called on successful device probe to enable runtime_pm */ sof_pdata->sof_probe_complete = sof_pci_probe_complete; -- cgit v1.2.3-59-g8ed1b From b1a4ee9fd5a2dfb0f23abe58377f816915ec14ba Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:21 +0200 Subject: ASoC: SOF: core: Implement firmware, topology path setup in core Use the information stored in ipc_file_profile_base by platforms to construct the paths, filenames that are going to be used to load the firmware and topology files. Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Makefile | 3 +- sound/soc/sof/core.c | 70 ++++++++++++++++++++-- sound/soc/sof/fw-file-profile.c | 130 ++++++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-priv.h | 7 +++ 4 files changed, 203 insertions(+), 7 deletions(-) create mode 100644 sound/soc/sof/fw-file-profile.c (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index ef6fd43d0b72..3624124575af 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -1,7 +1,8 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ - control.o trace.o iomem-utils.o sof-audio.o stream-ipc.o + control.o trace.o iomem-utils.o sof-audio.o stream-ipc.o\ + fw-file-profile.o # IPC implementations ifneq ($(CONFIG_SND_SOC_SOF_IPC3),) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index a87522ea4301..f1a083de9f9e 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -204,6 +204,67 @@ nocodec: return 0; } +static int sof_select_ipc_and_paths(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *plat_data = sdev->pdata; + struct sof_loadable_file_profile *base_profile = &plat_data->ipc_file_profile_base; + struct sof_loadable_file_profile out_profile; + struct device *dev = sdev->dev; + int ret; + + /* check IPC support */ + if (!(BIT(base_profile->ipc_type) & plat_data->desc->ipc_supported_mask)) { + dev_err(dev, + "ipc_type %d is not supported on this platform, mask is %#x\n", + base_profile->ipc_type, plat_data->desc->ipc_supported_mask); + return -EINVAL; + } + + if (base_profile->ipc_type != plat_data->desc->ipc_default) + dev_info(dev, + "Module parameter used, overriding default IPC %d to %d\n", + plat_data->desc->ipc_default, base_profile->ipc_type); + + if (base_profile->fw_path) + dev_dbg(dev, "Module parameter used, changed fw path to %s\n", + base_profile->fw_path); + else if (base_profile->fw_path_postfix) + dev_dbg(dev, "Path postfix appended to default fw path: %s\n", + base_profile->fw_path_postfix); + + if (base_profile->fw_lib_path) + dev_dbg(dev, "Module parameter used, changed fw_lib path to %s\n", + base_profile->fw_lib_path); + else if (base_profile->fw_lib_path_postfix) + dev_dbg(dev, "Path postfix appended to default fw_lib path: %s\n", + base_profile->fw_lib_path_postfix); + + if (base_profile->fw_name) + dev_dbg(dev, "Module parameter used, changed fw filename to %s\n", + base_profile->fw_name); + + if (base_profile->tplg_path) + dev_dbg(dev, "Module parameter used, changed tplg path to %s\n", + base_profile->tplg_path); + + if (base_profile->tplg_name) + dev_dbg(dev, "Module parameter used, changed tplg name to %s\n", + base_profile->tplg_name); + + ret = sof_create_ipc_file_profile(sdev, base_profile, &out_profile); + if (ret) + return ret; + + plat_data->ipc_type = out_profile.ipc_type; + plat_data->fw_filename = out_profile.fw_name; + plat_data->fw_filename_prefix = out_profile.fw_path; + plat_data->fw_lib_prefix = out_profile.fw_lib_path; + plat_data->tplg_filename_prefix = out_profile.tplg_path; + plat_data->tplg_filename = out_profile.tplg_name; + + return 0; +} + /* * FW Boot State Transition Diagram * @@ -442,12 +503,9 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) } } - /* check IPC support */ - if (!(BIT(plat_data->ipc_type) & plat_data->desc->ipc_supported_mask)) { - dev_err(dev, "ipc_type %d is not supported on this platform, mask is %#x\n", - plat_data->ipc_type, plat_data->desc->ipc_supported_mask); - return -EINVAL; - } + ret = sof_select_ipc_and_paths(sdev); + if (ret) + return ret; /* init ops, if necessary */ ret = sof_ops_init(sdev); diff --git a/sound/soc/sof/fw-file-profile.c b/sound/soc/sof/fw-file-profile.c new file mode 100644 index 000000000000..58b55516049e --- /dev/null +++ b/sound/soc/sof/fw-file-profile.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// + +#include +#include "sof-priv.h" + +static int +sof_file_profile_for_ipc_type(struct device *dev, + const struct sof_dev_desc *desc, + struct sof_loadable_file_profile *base_profile, + struct sof_loadable_file_profile *out_profile) +{ + enum sof_ipc_type ipc_type = base_profile->ipc_type; + bool fw_lib_path_allocated = false; + bool fw_path_allocated = false; + int ret = 0; + + /* firmware path */ + if (base_profile->fw_path) { + out_profile->fw_path = base_profile->fw_path; + } else if (base_profile->fw_path_postfix) { + out_profile->fw_path = devm_kasprintf(dev, GFP_KERNEL, "%s/%s", + desc->default_fw_path[ipc_type], + base_profile->fw_path_postfix); + if (!out_profile->fw_path) + return -ENOMEM; + + fw_path_allocated = true; + } else { + out_profile->fw_path = desc->default_fw_path[ipc_type]; + } + + /* firmware filename */ + if (base_profile->fw_name) + out_profile->fw_name = base_profile->fw_name; + else + out_profile->fw_name = desc->default_fw_filename[ipc_type]; + + + /* firmware library path */ + if (base_profile->fw_lib_path) { + out_profile->fw_lib_path = base_profile->fw_lib_path; + } else if (desc->default_lib_path[ipc_type]) { + if (base_profile->fw_lib_path_postfix) { + out_profile->fw_lib_path = devm_kasprintf(dev, + GFP_KERNEL, "%s/%s", + desc->default_lib_path[ipc_type], + base_profile->fw_lib_path_postfix); + if (!out_profile->fw_lib_path) { + ret = -ENOMEM; + goto out; + } + + fw_lib_path_allocated = true; + } else { + out_profile->fw_lib_path = desc->default_lib_path[ipc_type]; + } + } + + if (base_profile->fw_path_postfix) + out_profile->fw_path_postfix = base_profile->fw_path_postfix; + + if (base_profile->fw_lib_path_postfix) + out_profile->fw_lib_path_postfix = base_profile->fw_lib_path_postfix; + + /* topology path */ + if (base_profile->tplg_path) + out_profile->tplg_path = base_profile->tplg_path; + else + out_profile->tplg_path = desc->default_tplg_path[ipc_type]; + + /* topology name */ + if (base_profile->tplg_name) + out_profile->tplg_name = base_profile->tplg_name; + + out_profile->ipc_type = ipc_type; + +out: + if (ret) { + /* Free up path strings created with devm_kasprintf */ + if (fw_path_allocated) + devm_kfree(dev, out_profile->fw_path); + if (fw_lib_path_allocated) + devm_kfree(dev, out_profile->fw_lib_path); + + memset(out_profile, 0, sizeof(*out_profile)); + } + + return ret; +} + +static void sof_print_profile_info(struct device *dev, + struct sof_loadable_file_profile *profile) +{ + dev_info(dev, "Firmware paths/files for ipc type %d:\n", profile->ipc_type); + + dev_info(dev, " Firmware file: %s/%s\n", profile->fw_path, profile->fw_name); + if (profile->fw_lib_path) + dev_info(dev, " Firmware lib path: %s\n", profile->fw_lib_path); + if (profile->tplg_name) + dev_info(dev, " Topology file: %s/%s\n", profile->tplg_path, + profile->tplg_name); + else + dev_info(dev, " Topology path: %s\n", profile->tplg_path); +} + +int sof_create_ipc_file_profile(struct snd_sof_dev *sdev, + struct sof_loadable_file_profile *base_profile, + struct sof_loadable_file_profile *out_profile) +{ + const struct sof_dev_desc *desc = sdev->pdata->desc; + struct device *dev = sdev->dev; + int ret; + + memset(out_profile, 0, sizeof(*out_profile)); + + ret = sof_file_profile_for_ipc_type(dev, desc, base_profile, out_profile); + if (ret) + return ret; + + sof_print_profile_info(dev, out_profile); + + return 0; +} +EXPORT_SYMBOL(sof_create_ipc_file_profile); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index faa8a19ed737..6d7897bf9607 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -695,6 +695,13 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev); */ extern struct snd_compress_ops sof_compressed_ops; +/* + * Firmware (firmware, libraries, topologies) file location + */ +int sof_create_ipc_file_profile(struct snd_sof_dev *sdev, + struct sof_loadable_file_profile *base_profile, + struct sof_loadable_file_profile *out_profile); + /* * Firmware loading. */ -- cgit v1.2.3-59-g8ed1b From b2b0bba36f0a81743e7143a8801ca75d2238bdac Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:22 +0200 Subject: ASoC: SOF: sof-acpi-dev: Rely on core to create the file paths The core is now using the information from ipc_file_profile_base to create the paths for the loadable files, no need to set it in here anymore. Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-acpi-dev.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 87c0c2edc4c9..2977f0a63fba 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -74,18 +74,6 @@ int sof_acpi_probe(struct platform_device *pdev, const struct sof_dev_desc *desc sof_pdata->desc = desc; sof_pdata->dev = &pdev->dev; - sof_pdata->fw_filename = desc->default_fw_filename[SOF_IPC_TYPE_3]; - - /* alternate fw and tplg filenames ? */ - if (fw_path) - sof_pdata->fw_filename_prefix = fw_path; - else - sof_pdata->fw_filename_prefix = desc->default_fw_path[SOF_IPC_TYPE_3]; - - if (tplg_path) - sof_pdata->tplg_filename_prefix = tplg_path; - else - sof_pdata->tplg_filename_prefix = desc->default_tplg_path[SOF_IPC_TYPE_3]; sof_pdata->ipc_file_profile_base.ipc_type = desc->ipc_default; sof_pdata->ipc_file_profile_base.fw_path = fw_path; -- cgit v1.2.3-59-g8ed1b From 8616168928f278723fdc3f4d7cd3d611dcdae8f8 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:23 +0200 Subject: ASoC: SOF: sof-of-dev: Rely on core to create the file paths The core is now using the information from ipc_file_profile_base to create the paths for the loadable files, no need to set it in here anymore. Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-10-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-of-dev.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index 7b58f45790f7..fa92da5ee9b3 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -87,17 +87,6 @@ int sof_of_probe(struct platform_device *pdev) sof_pdata->desc = desc; sof_pdata->dev = &pdev->dev; - sof_pdata->fw_filename = desc->default_fw_filename[SOF_IPC_TYPE_3]; - - if (fw_path) - sof_pdata->fw_filename_prefix = fw_path; - else - sof_pdata->fw_filename_prefix = desc->default_fw_path[SOF_IPC_TYPE_3]; - - if (tplg_path) - sof_pdata->tplg_filename_prefix = tplg_path; - else - sof_pdata->tplg_filename_prefix = desc->default_tplg_path[SOF_IPC_TYPE_3]; sof_pdata->ipc_file_profile_base.ipc_type = desc->ipc_default; sof_pdata->ipc_file_profile_base.fw_path = fw_path; -- cgit v1.2.3-59-g8ed1b From 8a83f180abb5b95f524fc9b5eb2291f0e39bed30 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:24 +0200 Subject: ASoC: SOF: sof-pci-dev: Rely on core to create the file paths The core is now using the information from ipc_file_profile_base to create the paths for the loadable files, no need to set it in here anymore. Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-11-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 115 +++++++------------------------------------- 1 file changed, 17 insertions(+), 98 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index becc85b27d51..aab5c900cecf 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -233,120 +233,39 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) sof_pdata->desc = desc; sof_pdata->dev = dev; - sof_pdata->ipc_type = desc->ipc_default; + path_override = &sof_pdata->ipc_file_profile_base; if (sof_pci_ipc_type < 0) { - sof_pdata->ipc_type = desc->ipc_default; - } else { - dev_info(dev, "overriding default IPC %d to requested %d\n", - desc->ipc_default, sof_pci_ipc_type); - if (sof_pci_ipc_type >= SOF_IPC_TYPE_COUNT) { - dev_err(dev, "invalid request value %d\n", sof_pci_ipc_type); - ret = -EINVAL; - goto out; - } - if (!(BIT(sof_pci_ipc_type) & desc->ipc_supported_mask)) { - dev_err(dev, "invalid request value %d, supported mask is %#x\n", - sof_pci_ipc_type, desc->ipc_supported_mask); - ret = -EINVAL; - goto out; - } - sof_pdata->ipc_type = sof_pci_ipc_type; - } - - if (fw_filename) { - sof_pdata->fw_filename = fw_filename; - - dev_dbg(dev, "Module parameter used, changed fw filename to %s\n", - sof_pdata->fw_filename); + path_override->ipc_type = desc->ipc_default; + } else if (sof_pci_ipc_type < SOF_IPC_TYPE_COUNT) { + path_override->ipc_type = sof_pci_ipc_type; } else { - sof_pdata->fw_filename = desc->default_fw_filename[sof_pdata->ipc_type]; + dev_err(dev, "Invalid IPC type requested: %d\n", sof_pci_ipc_type); + ret = -EINVAL; + goto out; } - /* - * for platforms using the SOF community key, change the - * default path automatically to pick the right files from the - * linux-firmware tree. This can be overridden with the - * fw_path kernel parameter, e.g. for developers. - */ - - /* alternate fw and tplg filenames ? */ - if (fw_path) { - sof_pdata->fw_filename_prefix = fw_path; - - dev_dbg(dev, - "Module parameter used, changed fw path to %s\n", - sof_pdata->fw_filename_prefix); - - } else if (dmi_check_system(community_key_platforms) && sof_dmi_use_community_key) { - sof_pdata->fw_filename_prefix = - devm_kasprintf(dev, GFP_KERNEL, "%s/%s", - sof_pdata->desc->default_fw_path[sof_pdata->ipc_type], - "community"); - - dev_dbg(dev, - "Platform uses community key, changed fw path to %s\n", - sof_pdata->fw_filename_prefix); - } else { - sof_pdata->fw_filename_prefix = - sof_pdata->desc->default_fw_path[sof_pdata->ipc_type]; - } + path_override->fw_path = fw_path; + path_override->fw_name = fw_filename; + path_override->fw_lib_path = lib_path; + path_override->tplg_path = tplg_path; - if (lib_path) { - sof_pdata->fw_lib_prefix = lib_path; - - dev_dbg(dev, "Module parameter used, changed fw_lib path to %s\n", - sof_pdata->fw_lib_prefix); - - } else if (sof_pdata->desc->default_lib_path[sof_pdata->ipc_type]) { - if (dmi_check_system(community_key_platforms) && sof_dmi_use_community_key) { - sof_pdata->fw_lib_prefix = - devm_kasprintf(dev, GFP_KERNEL, "%s/%s", - sof_pdata->desc->default_lib_path[sof_pdata->ipc_type], - "community"); - - dev_dbg(dev, - "Platform uses community key, changed fw_lib path to %s\n", - sof_pdata->fw_lib_prefix); - } else { - sof_pdata->fw_lib_prefix = - sof_pdata->desc->default_lib_path[sof_pdata->ipc_type]; - } + if (dmi_check_system(community_key_platforms) && + sof_dmi_use_community_key) { + path_override->fw_path_postfix = "community"; + path_override->fw_lib_path_postfix = "community"; } - if (tplg_path) - sof_pdata->tplg_filename_prefix = tplg_path; - else - sof_pdata->tplg_filename_prefix = - sof_pdata->desc->default_tplg_path[sof_pdata->ipc_type]; - /* * the topology filename will be provided in the machine descriptor, unless * it is overridden by a module parameter or DMI quirk. */ if (tplg_filename) { - sof_pdata->tplg_filename = tplg_filename; - - dev_dbg(dev, "Module parameter used, changed tplg filename to %s\n", - sof_pdata->tplg_filename); + path_override->tplg_name = tplg_filename; } else { dmi_check_system(sof_tplg_table); if (sof_dmi_override_tplg_name) - sof_pdata->tplg_filename = sof_dmi_override_tplg_name; - } - - path_override = &sof_pdata->ipc_file_profile_base; - path_override->ipc_type = sof_pdata->ipc_type; - path_override->fw_path = fw_path; - path_override->fw_name = fw_filename; - path_override->fw_lib_path = lib_path; - path_override->tplg_path = tplg_path; - path_override->tplg_name = sof_pdata->tplg_filename; - - if (dmi_check_system(community_key_platforms) && - sof_dmi_use_community_key) { - path_override->fw_path_postfix = "community"; - path_override->fw_lib_path_postfix = "community"; + path_override->tplg_name = sof_dmi_override_tplg_name; } /* set callback to be called on successful device probe to enable runtime_pm */ -- cgit v1.2.3-59-g8ed1b From a5a65437b02df8b842c4620b0b776bcd91ce200a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:25 +0200 Subject: ASoC: SOF: core: Add helper for initialization of paths, ops Add sof_init_environment() as a helper function to contain path and ops initialization. Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 56 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 22 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index f1a083de9f9e..a2e9506e0f85 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -265,6 +265,38 @@ static int sof_select_ipc_and_paths(struct snd_sof_dev *sdev) return 0; } +static int sof_init_environment(struct snd_sof_dev *sdev) +{ + int ret; + + ret = sof_select_ipc_and_paths(sdev); + if (ret) + return ret; + + /* init ops, if necessary */ + ret = sof_ops_init(sdev); + if (ret < 0) + return ret; + + /* check all mandatory ops */ + if (!sof_ops(sdev) || !sof_ops(sdev)->probe) { + dev_err(sdev->dev, "missing mandatory ops\n"); + sof_ops_free(sdev); + return -EINVAL; + } + + if (!sdev->dspless_mode_selected && + (!sof_ops(sdev)->run || !sof_ops(sdev)->block_read || + !sof_ops(sdev)->block_write || !sof_ops(sdev)->send_msg || + !sof_ops(sdev)->load_firmware || !sof_ops(sdev)->ipc_msg_data)) { + dev_err(sdev->dev, "missing mandatory DSP ops\n"); + sof_ops_free(sdev); + return -EINVAL; + } + + return 0; +} + /* * FW Boot State Transition Diagram * @@ -503,31 +535,11 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) } } - ret = sof_select_ipc_and_paths(sdev); + /* Initialize loadable file paths and check the environment validity */ + ret = sof_init_environment(sdev); if (ret) return ret; - /* init ops, if necessary */ - ret = sof_ops_init(sdev); - if (ret < 0) - return ret; - - /* check all mandatory ops */ - if (!sof_ops(sdev) || !sof_ops(sdev)->probe) { - sof_ops_free(sdev); - dev_err(dev, "missing mandatory ops\n"); - return -EINVAL; - } - - if (!sdev->dspless_mode_selected && - (!sof_ops(sdev)->run || !sof_ops(sdev)->block_read || - !sof_ops(sdev)->block_write || !sof_ops(sdev)->send_msg || - !sof_ops(sdev)->load_firmware || !sof_ops(sdev)->ipc_msg_data)) { - sof_ops_free(sdev); - dev_err(dev, "missing mandatory DSP ops\n"); - return -EINVAL; - } - INIT_LIST_HEAD(&sdev->pcm_list); INIT_LIST_HEAD(&sdev->kcontrol_list); INIT_LIST_HEAD(&sdev->widget_list); -- cgit v1.2.3-59-g8ed1b From 9b6896538ea71b7c24da1ecb38738a311176f6a8 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:26 +0200 Subject: ASoC: SOF: Intel: Do not use resource managed allocation for ipc4_data Manage the ipc4_data allocation in code instead of devm since the ops_init might be called more than once due to IPC type fallback. Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-13-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/apl.c | 2 +- sound/soc/sof/intel/cnl.c | 2 +- sound/soc/sof/intel/hda-dai.c | 3 +++ sound/soc/sof/intel/icl.c | 2 +- sound/soc/sof/intel/lnl.c | 2 +- sound/soc/sof/intel/mtl.c | 2 +- sound/soc/sof/intel/skl.c | 2 +- sound/soc/sof/intel/tgl.c | 2 +- 8 files changed, 10 insertions(+), 7 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 776b66389c34..dee6c7f73e80 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -55,7 +55,7 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev) if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { struct sof_ipc4_fw_data *ipc4_data; - sdev->private = devm_kzalloc(sdev->dev, sizeof(*ipc4_data), GFP_KERNEL); + sdev->private = kzalloc(sizeof(*ipc4_data), GFP_KERNEL); if (!sdev->private) return -ENOMEM; diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 598cf50abadb..85e1e4760d0e 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -402,7 +402,7 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev) if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { struct sof_ipc4_fw_data *ipc4_data; - sdev->private = devm_kzalloc(sdev->dev, sizeof(*ipc4_data), GFP_KERNEL); + sdev->private = kzalloc(sizeof(*ipc4_data), GFP_KERNEL); if (!sdev->private) return -ENOMEM; diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index a20deaf3b428..f4cbc0ad5de3 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -621,6 +621,9 @@ void hda_ops_free(struct snd_sof_dev *sdev) if (!hda_use_tplg_nhlt) intel_nhlt_free(ipc4_data->nhlt); + + kfree(sdev->private); + sdev->private = NULL; } } EXPORT_SYMBOL_NS(hda_ops_free, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c index 8e29d6bb6fe8..040698591992 100644 --- a/sound/soc/sof/intel/icl.c +++ b/sound/soc/sof/intel/icl.c @@ -123,7 +123,7 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev) if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { struct sof_ipc4_fw_data *ipc4_data; - sdev->private = devm_kzalloc(sdev->dev, sizeof(*ipc4_data), GFP_KERNEL); + sdev->private = kzalloc(sizeof(*ipc4_data), GFP_KERNEL); if (!sdev->private) return -ENOMEM; diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index db94b45e53af..03308721ebd4 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -120,7 +120,7 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev) sof_lnl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position; - sdev->private = devm_kzalloc(sdev->dev, sizeof(struct sof_ipc4_fw_data), GFP_KERNEL); + sdev->private = kzalloc(sizeof(struct sof_ipc4_fw_data), GFP_KERNEL); if (!sdev->private) return -ENOMEM; diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 3ef9e5c37028..f941e2c49d78 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -709,7 +709,7 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev) sof_mtl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position; - sdev->private = devm_kzalloc(sdev->dev, sizeof(struct sof_ipc4_fw_data), GFP_KERNEL); + sdev->private = kzalloc(sizeof(struct sof_ipc4_fw_data), GFP_KERNEL); if (!sdev->private) return -ENOMEM; diff --git a/sound/soc/sof/intel/skl.c b/sound/soc/sof/intel/skl.c index d24e64e71b58..93824e6ce573 100644 --- a/sound/soc/sof/intel/skl.c +++ b/sound/soc/sof/intel/skl.c @@ -62,7 +62,7 @@ int sof_skl_ops_init(struct snd_sof_dev *sdev) /* probe/remove/shutdown */ sof_skl_ops.shutdown = hda_dsp_shutdown; - sdev->private = devm_kzalloc(sdev->dev, sizeof(*ipc4_data), GFP_KERNEL); + sdev->private = kzalloc(sizeof(*ipc4_data), GFP_KERNEL); if (!sdev->private) return -ENOMEM; diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index f7de1f5ba06d..d890cac6cb01 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -82,7 +82,7 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { struct sof_ipc4_fw_data *ipc4_data; - sdev->private = devm_kzalloc(sdev->dev, sizeof(*ipc4_data), GFP_KERNEL); + sdev->private = kzalloc(sizeof(*ipc4_data), GFP_KERNEL); if (!sdev->private) return -ENOMEM; -- cgit v1.2.3-59-g8ed1b From 6c393ebbd74ad341bcfb4e2d0091b2655fad45d0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:53:27 +0200 Subject: ASoC: SOF: core: Implement IPC version fallback if firmware files are missing If a firmware file is missing for the selected IPC type then try to switch to other supported IPC type and check if that one can be used instead. If for example a platform is changed to IPC4 as default version but the given machine does not yet have the needed topology file created then we will fall back to IPC3 which should have all the needed files. Relocate the sof_init_environment() to be done at a later phase, in sof_probe_continue(). This will only have changes in behavior if CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE is enabled (Intel HDA platforms) by not failing the module probe, but it is not going to be different case compared to for example failed firmware booting or topology loading error. Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20231129125327.23708-14-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 11 ++ sound/soc/sof/core.c | 104 ++++++++++++------ sound/soc/sof/fw-file-profile.c | 226 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 292 insertions(+), 49 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index a741ed96e789..32ffd345e07f 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -126,6 +126,17 @@ config SND_SOC_SOF_STRICT_ABI_CHECKS If you are not involved in SOF releases and CI development, select "N". +config SND_SOC_SOF_ALLOW_FALLBACK_TO_NEWER_IPC_VERSION + bool "SOF allow fallback to newer IPC version" + help + This option will allow the kernel to try to 'fallback' to a newer IPC + version if there are missing firmware files to satisfy the default IPC + version. + IPC version fallback to older versions is not affected by this option, + it is always available. + Say Y if you are involved in SOF development and need this option. + If not, select N. + config SND_SOC_SOF_DEBUG bool "SOF debugging features" help diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index a2e9506e0f85..a2afec8f5879 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -212,14 +212,6 @@ static int sof_select_ipc_and_paths(struct snd_sof_dev *sdev) struct device *dev = sdev->dev; int ret; - /* check IPC support */ - if (!(BIT(base_profile->ipc_type) & plat_data->desc->ipc_supported_mask)) { - dev_err(dev, - "ipc_type %d is not supported on this platform, mask is %#x\n", - base_profile->ipc_type, plat_data->desc->ipc_supported_mask); - return -EINVAL; - } - if (base_profile->ipc_type != plat_data->desc->ipc_default) dev_info(dev, "Module parameter used, overriding default IPC %d to %d\n", @@ -260,19 +252,14 @@ static int sof_select_ipc_and_paths(struct snd_sof_dev *sdev) plat_data->fw_filename_prefix = out_profile.fw_path; plat_data->fw_lib_prefix = out_profile.fw_lib_path; plat_data->tplg_filename_prefix = out_profile.tplg_path; - plat_data->tplg_filename = out_profile.tplg_name; return 0; } -static int sof_init_environment(struct snd_sof_dev *sdev) +static int validate_sof_ops(struct snd_sof_dev *sdev) { int ret; - ret = sof_select_ipc_and_paths(sdev); - if (ret) - return ret; - /* init ops, if necessary */ ret = sof_ops_init(sdev); if (ret < 0) @@ -297,6 +284,71 @@ static int sof_init_environment(struct snd_sof_dev *sdev) return 0; } +static int sof_init_sof_ops(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *plat_data = sdev->pdata; + struct sof_loadable_file_profile *base_profile = &plat_data->ipc_file_profile_base; + + /* check IPC support */ + if (!(BIT(base_profile->ipc_type) & plat_data->desc->ipc_supported_mask)) { + dev_err(sdev->dev, + "ipc_type %d is not supported on this platform, mask is %#x\n", + base_profile->ipc_type, plat_data->desc->ipc_supported_mask); + return -EINVAL; + } + + /* + * Save the selected IPC type and a topology name override before + * selecting ops since platform code might need this information + */ + plat_data->ipc_type = base_profile->ipc_type; + plat_data->tplg_filename = base_profile->tplg_name; + + return validate_sof_ops(sdev); +} + +static int sof_init_environment(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *plat_data = sdev->pdata; + struct sof_loadable_file_profile *base_profile = &plat_data->ipc_file_profile_base; + int ret; + + /* probe the DSP hardware */ + ret = snd_sof_probe(sdev); + if (ret < 0) { + dev_err(sdev->dev, "failed to probe DSP %d\n", ret); + sof_ops_free(sdev); + return ret; + } + + /* check machine info */ + ret = sof_machine_check(sdev); + if (ret < 0) { + dev_err(sdev->dev, "failed to get machine info %d\n", ret); + goto err_machine_check; + } + + ret = sof_select_ipc_and_paths(sdev); + if (!ret && plat_data->ipc_type != base_profile->ipc_type) { + /* IPC type changed, re-initialize the ops */ + sof_ops_free(sdev); + + ret = validate_sof_ops(sdev); + if (ret < 0) { + snd_sof_remove(sdev); + return ret; + } + } + +err_machine_check: + if (ret) { + snd_sof_remove(sdev); + sof_ops_free(sdev); + } + + return ret; +} + /* * FW Boot State Transition Diagram * @@ -342,23 +394,13 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) struct snd_sof_pdata *plat_data = sdev->pdata; int ret; - /* probe the DSP hardware */ - ret = snd_sof_probe(sdev); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to probe DSP %d\n", ret); - goto probe_err; - } + /* Initialize loadable file paths and check the environment validity */ + ret = sof_init_environment(sdev); + if (ret) + return ret; sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE); - /* check machine info */ - ret = sof_machine_check(sdev); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to get machine info %d\n", - ret); - goto dsp_err; - } - /* set up platform component driver */ snd_sof_new_platform_drv(sdev); @@ -478,9 +520,7 @@ fw_load_err: ipc_err: dbg_err: snd_sof_free_debug(sdev); -dsp_err: snd_sof_remove(sdev); -probe_err: snd_sof_remove_late(sdev); sof_ops_free(sdev); @@ -535,8 +575,8 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) } } - /* Initialize loadable file paths and check the environment validity */ - ret = sof_init_environment(sdev); + /* Initialize sof_ops based on the initial selected IPC version */ + ret = sof_init_sof_ops(sdev); if (ret) return ret; diff --git a/sound/soc/sof/fw-file-profile.c b/sound/soc/sof/fw-file-profile.c index 58b55516049e..138a1ca2c4a8 100644 --- a/sound/soc/sof/fw-file-profile.c +++ b/sound/soc/sof/fw-file-profile.c @@ -6,17 +6,99 @@ // Copyright(c) 2023 Intel Corporation. All rights reserved. // +#include #include +#include #include "sof-priv.h" +static int sof_test_firmware_file(struct device *dev, + struct sof_loadable_file_profile *profile, + enum sof_ipc_type *ipc_type_to_adjust) +{ + enum sof_ipc_type fw_ipc_type; + const struct firmware *fw; + const char *fw_filename; + const u32 *magic; + int ret; + + fw_filename = kasprintf(GFP_KERNEL, "%s/%s", profile->fw_path, + profile->fw_name); + if (!fw_filename) + return -ENOMEM; + + ret = firmware_request_nowarn(&fw, fw_filename, dev); + if (ret < 0) { + dev_dbg(dev, "Failed to open firmware file: %s\n", fw_filename); + kfree(fw_filename); + return ret; + } + + /* firmware file exists, check the magic number */ + magic = (const u32 *)fw->data; + switch (*magic) { + case SOF_EXT_MAN_MAGIC_NUMBER: + fw_ipc_type = SOF_IPC_TYPE_3; + break; + case SOF_EXT_MAN4_MAGIC_NUMBER: + fw_ipc_type = SOF_IPC_TYPE_4; + break; + default: + dev_err(dev, "Invalid firmware magic: %#x\n", *magic); + ret = -EINVAL; + goto out; + } + + if (ipc_type_to_adjust) { + *ipc_type_to_adjust = fw_ipc_type; + } else if (fw_ipc_type != profile->ipc_type) { + dev_err(dev, + "ipc type mismatch between %s and expected: %d vs %d\n", + fw_filename, fw_ipc_type, profile->ipc_type); + ret = -EINVAL; + } +out: + release_firmware(fw); + kfree(fw_filename); + + return ret; +} + +static int sof_test_topology_file(struct device *dev, + struct sof_loadable_file_profile *profile) +{ + const struct firmware *fw; + const char *tplg_filename; + int ret; + + if (!profile->tplg_path || !profile->tplg_name) + return 0; + + tplg_filename = kasprintf(GFP_KERNEL, "%s/%s", profile->tplg_path, + profile->tplg_name); + if (!tplg_filename) + return -ENOMEM; + + ret = firmware_request_nowarn(&fw, tplg_filename, dev); + if (!ret) + release_firmware(fw); + else + dev_dbg(dev, "Failed to open topology file: %s\n", tplg_filename); + + kfree(tplg_filename); + + return ret; +} + static int -sof_file_profile_for_ipc_type(struct device *dev, +sof_file_profile_for_ipc_type(struct snd_sof_dev *sdev, + enum sof_ipc_type ipc_type, const struct sof_dev_desc *desc, struct sof_loadable_file_profile *base_profile, struct sof_loadable_file_profile *out_profile) { - enum sof_ipc_type ipc_type = base_profile->ipc_type; + struct snd_sof_pdata *plat_data = sdev->pdata; bool fw_lib_path_allocated = false; + struct device *dev = sdev->dev; bool fw_path_allocated = false; int ret = 0; @@ -41,6 +123,25 @@ sof_file_profile_for_ipc_type(struct device *dev, else out_profile->fw_name = desc->default_fw_filename[ipc_type]; + /* + * Check the custom firmware path/filename and adjust the ipc_type to + * match with the existing file for the remaining path configuration. + * + * For default path and firmware name do a verification before + * continuing further. + */ + if (base_profile->fw_path || base_profile->fw_name) { + ret = sof_test_firmware_file(dev, out_profile, &ipc_type); + if (ret) + return ret; + + if (!(desc->ipc_supported_mask & BIT(ipc_type))) { + dev_err(dev, "Unsupported IPC type %d needed by %s/%s\n", + ipc_type, out_profile->fw_path, + out_profile->fw_name); + return -EINVAL; + } + } /* firmware library path */ if (base_profile->fw_lib_path) { @@ -75,11 +176,17 @@ sof_file_profile_for_ipc_type(struct device *dev, out_profile->tplg_path = desc->default_tplg_path[ipc_type]; /* topology name */ - if (base_profile->tplg_name) - out_profile->tplg_name = base_profile->tplg_name; + out_profile->tplg_name = plat_data->tplg_filename; out_profile->ipc_type = ipc_type; + /* Test only default firmware file */ + if (!base_profile->fw_path && !base_profile->fw_name) + ret = sof_test_firmware_file(dev, out_profile, NULL); + + if (!ret) + ret = sof_test_topology_file(dev, out_profile); + out: if (ret) { /* Free up path strings created with devm_kasprintf */ @@ -94,19 +201,76 @@ out: return ret; } -static void sof_print_profile_info(struct device *dev, +static void +sof_print_missing_firmware_info(struct snd_sof_dev *sdev, + enum sof_ipc_type ipc_type, + struct sof_loadable_file_profile *base_profile) +{ + struct snd_sof_pdata *plat_data = sdev->pdata; + const struct sof_dev_desc *desc = plat_data->desc; + struct device *dev = sdev->dev; + int ipc_type_count, i; + char *marker; + + dev_err(dev, "SOF firmware and/or topology file not found.\n"); + dev_info(dev, "Supported default profiles\n"); + + if (IS_ENABLED(CONFIG_SND_SOC_SOF_ALLOW_FALLBACK_TO_NEWER_IPC_VERSION)) + ipc_type_count = SOF_IPC_TYPE_COUNT - 1; + else + ipc_type_count = base_profile->ipc_type; + + for (i = 0; i <= ipc_type_count; i++) { + if (!(desc->ipc_supported_mask & BIT(i))) + continue; + + if (i == ipc_type) + marker = "Requested"; + else + marker = "Fallback"; + + dev_info(dev, "- ipc type %d (%s):\n", i, marker); + if (base_profile->fw_path_postfix) + dev_info(dev, " Firmware file: %s/%s/%s\n", + desc->default_fw_path[i], + base_profile->fw_path_postfix, + desc->default_fw_filename[i]); + else + dev_info(dev, " Firmware file: %s/%s\n", + desc->default_fw_path[i], + desc->default_fw_filename[i]); + + dev_info(dev, " Topology file: %s/%s\n", + desc->default_tplg_path[i], + plat_data->tplg_filename); + } + + if (base_profile->fw_path || base_profile->fw_name || + base_profile->tplg_path || base_profile->tplg_name) + dev_info(dev, "Verify the path/name override module parameters.\n"); + + dev_info(dev, "Check if you have 'sof-firmware' package installed.\n"); + dev_info(dev, "Optionally it can be manually downloaded from:\n"); + dev_info(dev, " https://github.com/thesofproject/sof-bin/\n"); +} + +static void sof_print_profile_info(struct snd_sof_dev *sdev, + enum sof_ipc_type ipc_type, struct sof_loadable_file_profile *profile) { + struct device *dev = sdev->dev; + + if (ipc_type != profile->ipc_type) + dev_info(dev, + "Using fallback IPC type %d (requested type was %d)\n", + profile->ipc_type, ipc_type); + dev_info(dev, "Firmware paths/files for ipc type %d:\n", profile->ipc_type); dev_info(dev, " Firmware file: %s/%s\n", profile->fw_path, profile->fw_name); if (profile->fw_lib_path) dev_info(dev, " Firmware lib path: %s\n", profile->fw_lib_path); - if (profile->tplg_name) - dev_info(dev, " Topology file: %s/%s\n", profile->tplg_path, - profile->tplg_name); - else - dev_info(dev, " Topology path: %s\n", profile->tplg_path); + dev_info(dev, " Topology file: %s/%s\n", profile->tplg_path, profile->tplg_name); } int sof_create_ipc_file_profile(struct snd_sof_dev *sdev, @@ -114,17 +278,45 @@ int sof_create_ipc_file_profile(struct snd_sof_dev *sdev, struct sof_loadable_file_profile *out_profile) { const struct sof_dev_desc *desc = sdev->pdata->desc; - struct device *dev = sdev->dev; - int ret; + int ipc_fallback_start, ret, i; memset(out_profile, 0, sizeof(*out_profile)); - ret = sof_file_profile_for_ipc_type(dev, desc, base_profile, out_profile); - if (ret) - return ret; + ret = sof_file_profile_for_ipc_type(sdev, base_profile->ipc_type, desc, + base_profile, out_profile); + if (!ret) + goto out; + + /* + * No firmware file was found for the requested IPC type, as fallback + * if SND_SOC_SOF_ALLOW_FALLBACK_TO_NEWER_IPC_VERSION is selected, check + * all IPC versions in a backwards direction (from newer to older) + * if SND_SOC_SOF_ALLOW_FALLBACK_TO_NEWER_IPC_VERSION is not selected, + * check only older IPC versions than the selected/default version + */ + if (IS_ENABLED(CONFIG_SND_SOC_SOF_ALLOW_FALLBACK_TO_NEWER_IPC_VERSION)) + ipc_fallback_start = SOF_IPC_TYPE_COUNT - 1; + else + ipc_fallback_start = (int)base_profile->ipc_type - 1; - sof_print_profile_info(dev, out_profile); + for (i = ipc_fallback_start; i >= 0 ; i--) { + if (i == base_profile->ipc_type || + !(desc->ipc_supported_mask & BIT(i))) + continue; - return 0; + ret = sof_file_profile_for_ipc_type(sdev, i, desc, base_profile, + out_profile); + if (!ret) + break; + } + +out: + if (ret) + sof_print_missing_firmware_info(sdev, base_profile->ipc_type, + base_profile); + else + sof_print_profile_info(sdev, base_profile->ipc_type, out_profile); + + return ret; } EXPORT_SYMBOL(sof_create_ipc_file_profile); -- cgit v1.2.3-59-g8ed1b From 2bd512626f8ea3957c981cadd2ebf75feff737dd Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 29 Nov 2023 14:20:21 +0200 Subject: ASoC: SOF: ipc4: check return value of snd_sof_ipc_msg_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit snd_sof_ipc_msg_data could return error. Signed-off-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20231129122021.679-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index a9d9800d2fcc..145d319e041f 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -713,7 +713,14 @@ static void sof_ipc4_rx_msg(struct snd_sof_dev *sdev) return; ipc4_msg->data_size = data_size; - snd_sof_ipc_msg_data(sdev, NULL, ipc4_msg->data_ptr, ipc4_msg->data_size); + err = snd_sof_ipc_msg_data(sdev, NULL, ipc4_msg->data_ptr, ipc4_msg->data_size); + if (err < 0) { + dev_err(sdev->dev, "failed to read IPC notification data: %d\n", err); + kfree(ipc4_msg->data_ptr); + ipc4_msg->data_ptr = NULL; + ipc4_msg->data_size = 0; + return; + } } /* Handle notifications with payload */ -- cgit v1.2.3-59-g8ed1b From 729bb2cd2e0601ac6d52c53535a543b9db196fad Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 29 Nov 2023 14:28:05 +0200 Subject: ASoC: SOF: ipc4: Move window offset configuration earlier With the added exception handling support if the firmware fails to boot up we are trying to do a panic dump from the telemetry slot. The slot offsets would have been configured only after receiving the FW_READY message which makes this panic dump unusable for early boot failures. With IPC4 the DSP window offsets are at standard places unlike IPC3 where the offsets needs to be queried from the FW_READY message. Move the offset configuration to sof_ipc4_init from the fw_ready handler. Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20231129122805.10635-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4.c | 55 ++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index 145d319e041f..ac5c6bc66d2a 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -576,40 +576,12 @@ EXPORT_SYMBOL(sof_ipc4_find_debug_slot_offset_by_type); static int ipc4_fw_ready(struct snd_sof_dev *sdev, struct sof_ipc4_msg *ipc4_msg) { - int inbox_offset, inbox_size, outbox_offset, outbox_size; - /* no need to re-check version/ABI for subsequent boots */ if (!sdev->first_boot) return 0; - /* Set up the windows for IPC communication */ - inbox_offset = snd_sof_dsp_get_mailbox_offset(sdev); - if (inbox_offset < 0) { - dev_err(sdev->dev, "%s: No mailbox offset\n", __func__); - return inbox_offset; - } - inbox_size = SOF_IPC4_MSG_MAX_SIZE; - outbox_offset = snd_sof_dsp_get_window_offset(sdev, SOF_IPC4_OUTBOX_WINDOW_IDX); - outbox_size = SOF_IPC4_MSG_MAX_SIZE; - - sdev->fw_info_box.offset = snd_sof_dsp_get_window_offset(sdev, SOF_IPC4_INBOX_WINDOW_IDX); - sdev->fw_info_box.size = sizeof(struct sof_ipc4_fw_registers); - sdev->dsp_box.offset = inbox_offset; - sdev->dsp_box.size = inbox_size; - sdev->host_box.offset = outbox_offset; - sdev->host_box.size = outbox_size; - - sdev->debug_box.offset = snd_sof_dsp_get_window_offset(sdev, - SOF_IPC4_DEBUG_WINDOW_IDX); - sof_ipc4_create_exception_debugfs_node(sdev); - dev_dbg(sdev->dev, "mailbox upstream 0x%x - size 0x%x\n", - inbox_offset, inbox_size); - dev_dbg(sdev->dev, "mailbox downstream 0x%x - size 0x%x\n", - outbox_offset, outbox_size); - dev_dbg(sdev->dev, "debug box 0x%x\n", sdev->debug_box.offset); - return sof_ipc4_init_msg_memory(sdev); } @@ -796,11 +768,38 @@ static const struct sof_ipc_pm_ops ipc4_pm_ops = { static int sof_ipc4_init(struct snd_sof_dev *sdev) { struct sof_ipc4_fw_data *ipc4_data = sdev->private; + int inbox_offset; mutex_init(&ipc4_data->pipeline_state_mutex); xa_init_flags(&ipc4_data->fw_lib_xa, XA_FLAGS_ALLOC); + /* Set up the windows for IPC communication */ + inbox_offset = snd_sof_dsp_get_mailbox_offset(sdev); + if (inbox_offset < 0) { + dev_err(sdev->dev, "%s: No mailbox offset\n", __func__); + return inbox_offset; + } + + sdev->dsp_box.offset = inbox_offset; + sdev->dsp_box.size = SOF_IPC4_MSG_MAX_SIZE; + sdev->host_box.offset = snd_sof_dsp_get_window_offset(sdev, + SOF_IPC4_OUTBOX_WINDOW_IDX); + sdev->host_box.size = SOF_IPC4_MSG_MAX_SIZE; + + sdev->debug_box.offset = snd_sof_dsp_get_window_offset(sdev, + SOF_IPC4_DEBUG_WINDOW_IDX); + + sdev->fw_info_box.offset = snd_sof_dsp_get_window_offset(sdev, + SOF_IPC4_INBOX_WINDOW_IDX); + sdev->fw_info_box.size = sizeof(struct sof_ipc4_fw_registers); + + dev_dbg(sdev->dev, "mailbox upstream %#x - size %#x\n", + sdev->dsp_box.offset, SOF_IPC4_MSG_MAX_SIZE); + dev_dbg(sdev->dev, "mailbox downstream %#x - size %#x\n", + sdev->host_box.offset, SOF_IPC4_MSG_MAX_SIZE); + dev_dbg(sdev->dev, "debug box %#x\n", sdev->debug_box.offset); + return 0; } -- cgit v1.2.3-59-g8ed1b From 8f464a410944650adc8d75c7711d7d56c5506da0 Mon Sep 17 00:00:00 2001 From: Baofeng Tian Date: Wed, 29 Nov 2023 14:22:34 +0200 Subject: ASoC: SOF: ipc4-topology: Add module ID print during module set up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This module ID will be used for module performance automatic analysis for different modules, module name, module ID and module instance ID will be combined as a new generated ID for current module, this ID will be further used by analysis tools to identify current module. Take below case as example: 0x030006 gain.11.1 3 is module instance ID, 6 is module ID and gain.11.1 is module name. For pipeline widget print, keep as it is. Signed-off-by: Baofeng Tian Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Chao Song Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20231129122234.14515-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 8ab9c42069ee..4e7ab4e562e5 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -2383,6 +2383,8 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget } if (swidget->id != snd_soc_dapm_scheduler) { + int module_id = msg->primary & SOF_IPC4_MOD_ID_MASK; + ret = sof_ipc4_widget_assign_instance_id(sdev, swidget); if (ret < 0) { dev_err(sdev->dev, "failed to assign instance id for %s\n", @@ -2398,9 +2400,15 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget msg->extension &= ~SOF_IPC4_MOD_EXT_PPL_ID_MASK; msg->extension |= SOF_IPC4_MOD_EXT_PPL_ID(pipe_widget->instance_id); + + dev_dbg(sdev->dev, "Create widget %s (pipe %d) - ID %d, instance %d, core %d\n", + swidget->widget->name, swidget->pipeline_id, module_id, + swidget->instance_id, swidget->core); + } else { + dev_dbg(sdev->dev, "Create pipeline %s (pipe %d) - instance %d, core %d\n", + swidget->widget->name, swidget->pipeline_id, + swidget->instance_id, swidget->core); } - 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; -- cgit v1.2.3-59-g8ed1b From d0ae9dc48e24f5f704abcbb2dca3e4651bf0ff59 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 4 Dec 2023 11:35:47 +0800 Subject: ASoC: SOF: Move sof_of_machine_select() to core.c from sof-of-dev.c Commit 014fdeb0d747 ("ASoC: SOF: Move sof_of_machine_select() to sof-of-dev.c from sof-audio.c") caused a circular dependency between the snd_sof and snd_sof_of modules: depmod: ERROR: Cycle detected: snd_sof -> snd_sof_of -> snd_sof depmod: ERROR: Found 2 modules in dependency cycles! Move the function back with sof_machine_select(). Fixes: 014fdeb0d747 ("ASoC: SOF: Move sof_of_machine_select() to sof-of-dev.c from sof-audio.c") Signed-off-by: Chen-Yu Tsai Acked-by: Peter Ujfalusi Reviewed-by: Daniel Baluta Link: https://lore.kernel.org/r/20231204033549.2020289-1-wenst@chromium.org Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 22 ++++++++++++++++++++++ sound/soc/sof/sof-of-dev.c | 23 ----------------------- sound/soc/sof/sof-of-dev.h | 9 --------- 3 files changed, 22 insertions(+), 32 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index a2afec8f5879..425b023b03b4 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -144,6 +144,28 @@ void sof_set_fw_state(struct snd_sof_dev *sdev, enum sof_fw_state new_state) } EXPORT_SYMBOL(sof_set_fw_state); +static struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *sof_pdata = sdev->pdata; + const struct sof_dev_desc *desc = sof_pdata->desc; + struct snd_sof_of_mach *mach = desc->of_machines; + + if (!mach) + return NULL; + + for (; mach->compatible; mach++) { + if (of_machine_is_compatible(mach->compatible)) { + sof_pdata->tplg_filename = mach->sof_tplg_filename; + if (mach->fw_filename) + sof_pdata->fw_filename = mach->fw_filename; + + return mach; + } + } + + return NULL; +} + /* SOF Driver enumeration */ static int sof_machine_check(struct snd_sof_dev *sdev) { diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index fa92da5ee9b3..b9a499e92b9a 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -41,29 +41,6 @@ static void sof_of_probe_complete(struct device *dev) pm_runtime_enable(dev); } -struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev) -{ - struct snd_sof_pdata *sof_pdata = sdev->pdata; - const struct sof_dev_desc *desc = sof_pdata->desc; - struct snd_sof_of_mach *mach = desc->of_machines; - - if (!mach) - return NULL; - - for (; mach->compatible; mach++) { - if (of_machine_is_compatible(mach->compatible)) { - sof_pdata->tplg_filename = mach->sof_tplg_filename; - if (mach->fw_filename) - sof_pdata->fw_filename = mach->fw_filename; - - return mach; - } - } - - return NULL; -} -EXPORT_SYMBOL(sof_of_machine_select); - int sof_of_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; diff --git a/sound/soc/sof/sof-of-dev.h b/sound/soc/sof/sof-of-dev.h index 547e358a37e3..b6cc70595f3b 100644 --- a/sound/soc/sof/sof-of-dev.h +++ b/sound/soc/sof/sof-of-dev.h @@ -16,15 +16,6 @@ struct snd_sof_of_mach { const char *sof_tplg_filename; }; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_OF_DEV) -struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev); -#else -static inline struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev) -{ - return NULL; -} -#endif - extern const struct dev_pm_ops sof_of_pm; int sof_of_probe(struct platform_device *pdev); -- cgit v1.2.3-59-g8ed1b From 2f03970198d6438d95b96f69041254bd39aafed0 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 4 Dec 2023 15:47:10 -0600 Subject: ASoC: SOF: topology: Use partial match for disconnecting DAI link and DAI widget We use partial match for connecting DAI link and DAI widget. We need to use partial match for disconnecting, too. Fixes: fe88788779fc ("ASoC: SOF: topology: Use partial match for connecting DAI link and DAI widget") Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20231204214713.208951-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 9f717366cddc..c1f66ba0e987 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1135,7 +1135,7 @@ static void sof_disconnect_dai_widget(struct snd_soc_component *scomp, list_for_each_entry(rtd, &card->rtd_list, list) { /* does stream match DAI link ? */ if (!rtd->dai_link->stream_name || - strcmp(sname, rtd->dai_link->stream_name)) + !strstr(rtd->dai_link->stream_name, sname)) continue; for_each_rtd_cpu_dais(rtd, i, cpu_dai) -- cgit v1.2.3-59-g8ed1b From ebd12b2ca6145550a7e42cd2320870db02dd0f3c Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Mon, 4 Dec 2023 15:47:13 -0600 Subject: ASoC: SOF: Wire up buffer flags Buffer flags have been in firmware for ages but were never fully implemented in the topology/kernel system. This commit finishes off the implementation. Reviewed-by: Ranjani Sridharan Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20231204214713.208951-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 1 + sound/soc/sof/ipc3-topology.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'sound/soc/sof') diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 0fb39780f9bd..ee5708934614 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -35,6 +35,7 @@ /* buffers */ #define SOF_TKN_BUF_SIZE 100 #define SOF_TKN_BUF_CAPS 101 +#define SOF_TKN_BUF_FLAGS 102 /* DAI */ /* Token retired with ABI 3.2, do not use for new capabilities diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index 7a4932c152a9..a8e0054cb8a6 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -72,6 +72,8 @@ static const struct sof_topology_token buffer_tokens[] = { offsetof(struct sof_ipc_buffer, size)}, {SOF_TKN_BUF_CAPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, offsetof(struct sof_ipc_buffer, caps)}, + {SOF_TKN_BUF_FLAGS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_buffer, flags)}, }; /* DAI */ -- cgit v1.2.3-59-g8ed1b From f31c166a5027e927e5c032d40ef2e484d9ecd612 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 4 Dec 2023 15:44:07 -0600 Subject: ASoC: SOF: Intel: lnl: add core get and set support for dsp core Driver uses get and set ops to change the power state of dsp core. Closes: https://github.com/thesofproject/sof/issues/8478 Signed-off-by: Rander Wang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20231204214407.208528-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/lnl.c | 4 ++++ sound/soc/sof/intel/mtl.c | 4 ++-- sound/soc/sof/intel/mtl.h | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 03308721ebd4..a095f5bcf50d 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -120,6 +120,10 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev) sof_lnl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position; + /* dsp core get/put */ + sof_lnl_ops.core_get = mtl_dsp_core_get; + sof_lnl_ops.core_put = mtl_dsp_core_put; + sdev->private = kzalloc(sizeof(struct sof_ipc4_fw_data), GFP_KERNEL); if (!sdev->private) return -ENOMEM; diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index f941e2c49d78..3121a89219dd 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -638,7 +638,7 @@ u64 mtl_dsp_get_stream_hda_link_position(struct snd_sof_dev *sdev, return ((u64)llp_u << 32) | llp_l; } -static int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core) +int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core) { const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; @@ -651,7 +651,7 @@ static int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core) return 0; } -static int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core) +int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core) { const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; int ret; diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index 95696b3d7c4c..cc5a1f46fd09 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -106,3 +106,6 @@ void mtl_ipc_dump(struct snd_sof_dev *sdev); u64 mtl_dsp_get_stream_hda_link_position(struct snd_sof_dev *sdev, struct snd_soc_component *component, struct snd_pcm_substream *substream); + +int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core); +int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core); -- cgit v1.2.3-59-g8ed1b From ce17aa4cf2db7d6b95a3f854ac52d0d49881dd49 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 7 Dec 2023 11:54:25 +0200 Subject: ASoC: SOF: Intel: hda-codec: Delay the codec device registration The current code flow is: 1. snd_hdac_device_register() 2. set parameters needed by the hdac driver 3. request_codec_module() the hdac driver is probed at this point During boot the codec drivers are not loaded when the hdac device is registered, it is going to be probed later when loading the codec module, which point the parameters are set. On module remove/insert rmmod snd_sof_pci_intel_tgl modprobe snd_sof_pci_intel_tgl The codec module remains loaded and the driver will be probed when the hdac device is created right away, before the parameters for the driver has been configured: 1. snd_hdac_device_register() the hdac driver is probed at this point 2. set parameters needed by the hdac driver 3. request_codec_module() will be a NOP as the module is already loaded Move the snd_hdac_device_register() later, to be done right before requesting the codec module to make sure that the parameters are all set before the device is created: 1. set parameters needed by the hdac driver 2. snd_hdac_device_register() 3. request_codec_module() This way at the hdac driver probe all parameters will be set in all cases. Link: https://github.com/thesofproject/linux/issues/4731 Fixes: a0575b4add21 ("ASoC: hdac_hda: Conditionally register dais for HDMI and Analog") Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20231207095425.19597-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-codec.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 28ecbebb4b84..9f84b0d287a5 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -54,8 +54,16 @@ static int request_codec_module(struct hda_codec *codec) static int hda_codec_load_module(struct hda_codec *codec) { - int ret = request_codec_module(codec); + int ret; + + ret = snd_hdac_device_register(&codec->core); + if (ret) { + dev_err(&codec->core.dev, "failed to register hdac device\n"); + put_device(&codec->core.dev); + return ret; + } + ret = request_codec_module(codec); if (ret <= 0) { codec->probe_id = HDA_CODEC_ID_GENERIC; ret = request_codec_module(codec); @@ -116,7 +124,6 @@ EXPORT_SYMBOL_NS_GPL(hda_codec_jack_check, SND_SOC_SOF_HDA_AUDIO_CODEC); static struct hda_codec *hda_codec_device_init(struct hdac_bus *bus, int addr, int type) { struct hda_codec *codec; - int ret; codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr); if (IS_ERR(codec)) { @@ -126,13 +133,6 @@ static struct hda_codec *hda_codec_device_init(struct hdac_bus *bus, int addr, i codec->core.type = type; - ret = snd_hdac_device_register(&codec->core); - if (ret) { - dev_err(bus->dev, "failed to register hdac device\n"); - put_device(&codec->core.dev); - return ERR_PTR(ret); - } - return codec; } -- cgit v1.2.3-59-g8ed1b From 855a4772be9dc777cbcd580c8a07d9c54908219b Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Fri, 15 Dec 2023 16:31:01 +0800 Subject: ASoC: SOF: IPC4: query fw_context_save feature from fw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Driver queries fw_context_save feature when fw is ready and can skip library reload with this feature since library is saved in persistent memory. The default value of fw_context_save is true unless fw reports false. Signed-off-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Link: https://msgid.link/r/20231215083102.3064200-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/lnl.c | 2 ++ sound/soc/sof/intel/mtl.c | 2 ++ sound/soc/sof/intel/tgl.c | 2 ++ sound/soc/sof/ipc4-loader.c | 3 +++ sound/soc/sof/ipc4-priv.h | 1 + 5 files changed, 10 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index a095f5bcf50d..30712ea05a7a 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -133,6 +133,8 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev) ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2; + ipc4_data->fw_context_save = true; + /* External library loading support */ ipc4_data->load_library = hda_dsp_ipc4_load_library; diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 3121a89219dd..c14a80dd90fd 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -718,6 +718,8 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev) ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2; + ipc4_data->fw_context_save = true; + /* External library loading support */ ipc4_data->load_library = hda_dsp_ipc4_load_library; diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index d890cac6cb01..c2bb04c89b9d 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -91,6 +91,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2; + ipc4_data->fw_context_save = true; + /* External library loading support */ ipc4_data->load_library = hda_dsp_ipc4_load_library; diff --git a/sound/soc/sof/ipc4-loader.c b/sound/soc/sof/ipc4-loader.c index eaa04762eb11..3539b0a66e1b 100644 --- a/sound/soc/sof/ipc4-loader.c +++ b/sound/soc/sof/ipc4-loader.c @@ -391,6 +391,9 @@ int sof_ipc4_query_fw_configuration(struct snd_sof_dev *sdev) goto out; } break; + case SOF_IPC4_FW_CONTEXT_SAVE: + ipc4_data->fw_context_save = *tuple->value; + break; default: break; } diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h index fea93b693f4d..1d39836d5efa 100644 --- a/sound/soc/sof/ipc4-priv.h +++ b/sound/soc/sof/ipc4-priv.h @@ -81,6 +81,7 @@ struct sof_ipc4_fw_data { u32 mtrace_log_bytes; int max_num_pipelines; u32 max_libs_count; + bool fw_context_save; int (*load_library)(struct snd_sof_dev *sdev, struct sof_ipc4_fw_library *fw_lib, bool reload); -- cgit v1.2.3-59-g8ed1b From 3a0e7bb86f8728d94d55c56fb73e86be7976c163 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Fri, 15 Dec 2023 16:31:02 +0800 Subject: ASoC: SOF: Intel: check fw_context_save for library reload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If fw_context_save is defined by fw, driver can skip library reload on d3 exit or reload library. Signed-off-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Link: https://msgid.link/r/20231215083102.3064200-4-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 1805cf754beb..b81f231abee3 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -519,14 +519,15 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, struct sof_ipc4_fw_library *fw_lib, bool reload) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + struct sof_ipc4_fw_data *ipc4_data = sdev->private; struct hdac_ext_stream *hext_stream; struct firmware stripped_firmware; struct sof_ipc4_msg msg = {}; struct snd_dma_buffer dmab; int ret, ret1; - /* IMR booting will restore the libraries as well, skip the loading */ - if (reload && hda->booted_from_imr) + /* if IMR booting is enabled and fw context is saved for D3 state, skip the loading */ + if (reload && hda->booted_from_imr && ipc4_data->fw_context_save) return 0; /* the fw_lib has been verified during loading, we can trust the validity here */ -- cgit v1.2.3-59-g8ed1b From 02842209fc29bddb2b673ceb8f681267857c4bc1 Mon Sep 17 00:00:00 2001 From: Wang Jinchao Date: Fri, 15 Dec 2023 17:20:00 +0800 Subject: ASoC: SOF: amd: remove duplicated including remove the second \#include "../sof-audio.h" Signed-off-by: Wang Jinchao Link: https://msgid.link/r/202312151719+0800-wangjinchao@xfusion.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-common.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c index 3a0c7688dcfe..2d72c6d55dc8 100644 --- a/sound/soc/sof/amd/acp-common.c +++ b/sound/soc/sof/amd/acp-common.c @@ -13,7 +13,6 @@ #include "../sof-priv.h" #include "../sof-audio.h" #include "../ops.h" -#include "../sof-audio.h" #include "acp.h" #include "acp-dsp-offset.h" #include -- cgit v1.2.3-59-g8ed1b From e8776ff9ce9f5a8a9d8294101fd2924cebdd2da1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 19 Dec 2023 05:10:19 +0000 Subject: ASoC: sof: use snd_soc_dummy_dlc We already have snd_soc_dummy_dlc. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/8734vy93r8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-client-probes.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c index 7cc9e8f18de7..30f771ac7bbf 100644 --- a/sound/soc/sof/sof-client-probes.c +++ b/sound/soc/sof/sof-client-probes.c @@ -381,8 +381,6 @@ static const struct snd_soc_component_driver sof_probes_component = { .legacy_dai_naming = 1, }; -SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); - static int sof_probes_client_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id) { @@ -475,7 +473,7 @@ static int sof_probes_client_probe(struct auxiliary_device *auxdev, links[0].cpus = &cpus[0]; links[0].num_cpus = 1; links[0].cpus->dai_name = "Probe Extraction CPU DAI"; - links[0].codecs = dummy; + links[0].codecs = &snd_soc_dummy_dlc; links[0].num_codecs = 1; links[0].platforms = platform_component; links[0].num_platforms = ARRAY_SIZE(platform_component); -- cgit v1.2.3-59-g8ed1b From 802134c8c2c8889f7cc504ab1ba6ada9816ca969 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 19 Dec 2023 16:54:09 +0530 Subject: ASoC: SOF: amd: Refactor spinlock_irq(&sdev->ipc_lock) sequence in irq_handler Refactor spinlock_irq(&sdev->ipc_lock) sequence in irq_handler to avoid race conditions for acquiring hw_semaphore. Signed-off-by: Venkata Prasad Potturu Link: https://msgid.link/r/20231219112416.3334928-1-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-ipc.c | 4 +--- sound/soc/sof/amd/acp.c | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/amd/acp-ipc.c b/sound/soc/sof/amd/acp-ipc.c index fcb54f545fea..2743f07a5e08 100644 --- a/sound/soc/sof/amd/acp-ipc.c +++ b/sound/soc/sof/amd/acp-ipc.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2021 Advanced Micro Devices, Inc. +// Copyright(c) 2021, 2023 Advanced Micro Devices, Inc. // // Authors: Balakishore Pati // Ajit Kumar Pandey @@ -188,13 +188,11 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context) dsp_ack = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_ack_write); if (dsp_ack) { - spin_lock_irq(&sdev->ipc_lock); /* handle immediate reply from DSP core */ acp_dsp_ipc_get_reply(sdev); snd_sof_ipc_reply(sdev, 0); /* set the done bit */ acp_dsp_ipc_dsp_done(sdev); - spin_unlock_irq(&sdev->ipc_lock); ipc_irq = true; } diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index 603ea5fc0d0d..7860724c4d2d 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -343,11 +343,13 @@ static irqreturn_t acp_irq_thread(int irq, void *context) const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); unsigned int count = ACP_HW_SEM_RETRY_COUNT; + spin_lock_irq(&sdev->ipc_lock); while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) { /* Wait until acquired HW Semaphore lock or timeout */ count--; if (!count) { dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__); + spin_unlock_irq(&sdev->ipc_lock); return IRQ_NONE; } } @@ -356,6 +358,7 @@ static irqreturn_t acp_irq_thread(int irq, void *context) /* Unlock or Release HW Semaphore */ snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0); + spin_unlock_irq(&sdev->ipc_lock); return IRQ_HANDLED; }; -- cgit v1.2.3-59-g8ed1b From 3953de2dbdcd0592aa7f877b67135a51e18f006a Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 19 Dec 2023 16:54:10 +0530 Subject: ASoC: SOF: Refactor sof_i2s_tokens reading to update acpbt dai Refactor sof_i2s_tokens reading to update config->acpbt. Signed-off-by: Venkata Prasad Potturu Link: https://msgid.link/r/20231219112416.3334928-2-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-topology.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index a8e0054cb8a6..914eb187c5ac 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -1219,6 +1219,7 @@ static int sof_link_acp_bt_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); @@ -1227,12 +1228,14 @@ static int sof_link_acp_bt_load(struct snd_soc_component *scomp, struct snd_sof_ memset(&config->acpbt, 0, sizeof(config->acpbt)); config->hdr.size = size; - config->acpbt.fsync_rate = le32_to_cpu(hw_config->fsync_rate); - config->acpbt.tdm_slots = le32_to_cpu(hw_config->tdm_slots); + ret = sof_update_ipc_object(scomp, &config->acpbt, SOF_ACPI2S_TOKENS, slink->tuples, + slink->num_tuples, size, slink->num_hw_configs); + if (ret < 0) + return ret; - dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d\n", + dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d tdm_mode %d\n", config->dai_index, config->acpbt.tdm_slots, - config->acpbt.fsync_rate); + config->acpbt.fsync_rate, config->acpbt.tdm_mode); dai->number_configs = 1; dai->current_config = 0; -- cgit v1.2.3-59-g8ed1b From de111c9b521ddea4c7609155a617b5a0e93ad833 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 19 Dec 2023 16:54:11 +0530 Subject: ASoC: SOF: Add i2s bt dai configuration support for AMD platforms Add support for i2s bt dai configuration from topology. Signed-off-by: Venkata Prasad Potturu Link: https://msgid.link/r/20231219112416.3334928-3-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index c1f66ba0e987..22467c17f2b2 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1954,6 +1954,7 @@ 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_BT: case SOF_DAI_AMD_SP: case SOF_DAI_AMD_HS: case SOF_DAI_AMD_SP_VIRTUAL: -- cgit v1.2.3-59-g8ed1b From ced7151b9b0c74af1bc05ac4ad93648900709bb0 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 19 Dec 2023 16:54:12 +0530 Subject: ASoC: SOF: Rename amd_bt sof_dai_type Rename amd_bt sof_dai_type from ACP to ACP_BT. Signed-off-by: Venkata Prasad Potturu Link: https://msgid.link/r/20231219112416.3334928-4-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 22467c17f2b2..dd5a903a0515 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -289,7 +289,7 @@ static const struct sof_dai_types sof_dais[] = { {"ALH", SOF_DAI_INTEL_ALH}, {"SAI", SOF_DAI_IMX_SAI}, {"ESAI", SOF_DAI_IMX_ESAI}, - {"ACP", SOF_DAI_AMD_BT}, + {"ACPBT", SOF_DAI_AMD_BT}, {"ACPSP", SOF_DAI_AMD_SP}, {"ACPDMIC", SOF_DAI_AMD_DMIC}, {"ACPHS", SOF_DAI_AMD_HS}, -- cgit v1.2.3-59-g8ed1b From 55d7bbe433467a64ac82c41b4efd425aa24acdce Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 19 Dec 2023 16:54:13 +0530 Subject: ASoC: SOF: amd: Add acp-psp mailbox interface for iram-dram fence register modification Add acp-psp mailbox communication interface for iram-dram size modification to notify psp. Signed-off-by: Venkata Prasad Potturu Link: https://msgid.link/r/20231219112416.3334928-5-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp.c | 11 +++++++++++ sound/soc/sof/amd/acp.h | 5 +++++ 2 files changed, 16 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index 7860724c4d2d..32a741fcb84f 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -278,6 +278,17 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr, return ret; } + /* psp_send_cmd only required for vangogh platform (rev - 5) */ + if (desc->rev == 5) { + /* Modify IRAM and DRAM size */ + ret = psp_send_cmd(adata, MBOX_ACP_IRAM_DRAM_FENCE_COMMAND | IRAM_DRAM_FENCE_2); + if (ret) + return ret; + ret = psp_send_cmd(adata, MBOX_ACP_IRAM_DRAM_FENCE_COMMAND | MBOX_ISREADY_FLAG); + if (ret) + return ret; + } + ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, ACP_SHA_DSP_FW_QUALIFIER, fw_qualifier, fw_qualifier & DSP_FW_RUN_ENABLE, ACP_REG_POLL_INTERVAL, ACP_DMA_COMPLETE_TIMEOUT_US); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index c536cfde0e44..c645aee216fd 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -74,9 +74,14 @@ #define MP0_C2PMSG_114_REG 0x3810AC8 #define MP0_C2PMSG_73_REG 0x3810A24 #define MBOX_ACP_SHA_DMA_COMMAND 0x70000 +#define MBOX_ACP_IRAM_DRAM_FENCE_COMMAND 0x80000 #define MBOX_DELAY_US 1000 #define MBOX_READY_MASK 0x80000000 #define MBOX_STATUS_MASK 0xFFFF +#define MBOX_ISREADY_FLAG 0x40000000 +#define IRAM_DRAM_FENCE_0 0X0 +#define IRAM_DRAM_FENCE_1 0X01 +#define IRAM_DRAM_FENCE_2 0X02 #define BOX_SIZE_512 0x200 #define BOX_SIZE_1024 0x400 -- cgit v1.2.3-59-g8ed1b From b6190c452a2264ccd88c849b91990fe854a7ec72 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 27 Dec 2023 17:27:43 +0800 Subject: ASoC: SOF: imx: Add SNDRV_PCM_INFO_BATCH flag The sof imx pcm device is a device which should support double buffering. Found this issue with pipewire. When there is no SNDRV_PCM_INFO_BATCH flag in driver, the pipewire will set headroom to be zero, and because sof pcm device don't support residue report, when the latency setting is small, the "delay" always larger than "target" in alsa-pcm.c, that reading next period data is not scheduled on time. With SNDRV_PCM_INFO_BATCH flag in driver, the pipewire will select a smaller period size for device, then the task of reading next period data will be scheduled on time. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1703669263-13832-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 1 + sound/soc/sof/imx/imx8m.c | 1 + sound/soc/sof/imx/imx8ulp.c | 1 + 3 files changed, 3 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 170740bce839..d777e70250ef 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -603,6 +603,7 @@ static struct snd_sof_dsp_ops sof_imx8x_ops = { SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP }; diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index f088fd1a672b..1b976fa500aa 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -472,6 +472,7 @@ static struct snd_sof_dsp_ops sof_imx8m_ops = { SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; diff --git a/sound/soc/sof/imx/imx8ulp.c b/sound/soc/sof/imx/imx8ulp.c index ca6edb85ff71..2badca75782b 100644 --- a/sound/soc/sof/imx/imx8ulp.c +++ b/sound/soc/sof/imx/imx8ulp.c @@ -463,6 +463,7 @@ static struct snd_sof_dsp_ops sof_imx8ulp_ops = { SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, /* PM */ -- cgit v1.2.3-59-g8ed1b