diff options
Diffstat (limited to 'sound/soc/sof')
-rw-r--r-- | sound/soc/sof/amd/Kconfig | 7 | ||||
-rw-r--r-- | sound/soc/sof/amd/acp-dsp-offset.h | 10 | ||||
-rw-r--r-- | sound/soc/sof/amd/acp.c | 135 | ||||
-rw-r--r-- | sound/soc/sof/amd/acp.h | 7 | ||||
-rw-r--r-- | sound/soc/sof/amd/pci-acp70.c | 10 | ||||
-rw-r--r-- | sound/soc/sof/core.c | 10 | ||||
-rw-r--r-- | sound/soc/sof/imx/imx8.c | 24 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda.h | 1 | ||||
-rw-r--r-- | sound/soc/sof/intel/pci-ptl.c | 30 | ||||
-rw-r--r-- | sound/soc/sof/intel/ptl.c | 23 | ||||
-rw-r--r-- | sound/soc/sof/ipc4-pcm.c | 3 | ||||
-rw-r--r-- | sound/soc/sof/sof-pci-dev.c | 16 | ||||
-rw-r--r-- | sound/soc/sof/topology.c | 97 |
13 files changed, 300 insertions, 73 deletions
diff --git a/sound/soc/sof/amd/Kconfig b/sound/soc/sof/amd/Kconfig index 3ea82fa72e35..05faf1c6d6fc 100644 --- a/sound/soc/sof/amd/Kconfig +++ b/sound/soc/sof/amd/Kconfig @@ -94,13 +94,14 @@ config SND_SOC_SOF_AMD_ACP63 If unsure select "N". config SND_SOC_SOF_AMD_ACP70 - tristate "SOF support for ACP7.0 platform" + tristate "SOF support for ACP7.0/ACP7.1 platforms" depends on SND_SOC_SOF_PCI depends on AMD_NODE select SND_SOC_SOF_AMD_COMMON + select SND_SOC_SOF_AMD_SOUNDWIRE_LINK_BASELINE help Select this option for SOF support on - AMD ACP7.0 version based platforms. - Say Y if you want to enable SOF on ACP7.0 based platform. + AMD ACP7.0/ACP7.1 version based platforms. + Say Y if you want to enable SOF on ACP7.0/ACP7.1 based platforms. endif diff --git a/sound/soc/sof/amd/acp-dsp-offset.h b/sound/soc/sof/amd/acp-dsp-offset.h index ecdcae07ace7..08583a91afbc 100644 --- a/sound/soc/sof/amd/acp-dsp-offset.h +++ b/sound/soc/sof/amd/acp-dsp-offset.h @@ -130,4 +130,14 @@ #define ACP_SW0_EN 0x3000 #define ACP_SW1_EN 0x3C00 +#define ACP70_PME_EN 0x1400 +#define ACP70_EXTERNAL_INTR_CNTL1 0x1A08 +#define ACP70_SW0_WAKE_EN 0x1458 +#define ACP70_SW1_WAKE_EN 0x1460 +#define ACP70_SDW_HOST_WAKE_MASK 0x0C00000 +#define ACP70_SDW0_HOST_WAKE_STAT BIT(24) +#define ACP70_SDW1_HOST_WAKE_STAT BIT(25) +#define ACP70_SDW0_PME_STAT BIT(26) +#define ACP70_SDW1_PME_STAT BIT(27) + #endif diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index 7c6d647fa253..7132916aa253 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -16,7 +16,7 @@ #include <linux/module.h> #include <linux/pci.h> -#include <asm/amd_node.h> +#include <asm/amd/node.h> #include "../ops.h" #include "acp.h" @@ -58,6 +58,7 @@ static void init_dma_descriptor(struct acp_dev_data *adata) switch (acp_data->pci_rev) { case ACP70_PCI_ID: + case ACP71_PCI_ID: acp_dma_desc_base_addr = ACP70_DMA_DESC_BASE_ADDR; acp_dma_desc_max_num_dscr = ACP70_DMA_DESC_MAX_NUM_DSCR; break; @@ -97,6 +98,7 @@ static int config_dma_channel(struct acp_dev_data *adata, unsigned int ch, switch (acp_data->pci_rev) { case ACP70_PCI_ID: + case ACP71_PCI_ID: acp_dma_cntl_0 = ACP70_DMA_CNTL_0; acp_dma_ch_rst_sts = ACP70_DMA_CH_RST_STS; acp_dma_dscr_err_sts_0 = ACP70_DMA_ERR_STS_0; @@ -336,6 +338,7 @@ int acp_dma_status(struct acp_dev_data *adata, unsigned char ch) switch (adata->pci_rev) { case ACP70_PCI_ID: + case ACP71_PCI_ID: acp_dma_ch_sts = ACP70_DMA_CH_STS; break; default: @@ -383,6 +386,69 @@ static int acp_memory_init(struct snd_sof_dev *sdev) return 0; } +static void amd_sof_handle_acp70_sdw_wake_event(struct acp_dev_data *adata) +{ + struct amd_sdw_manager *amd_manager; + + if (adata->acp70_sdw0_wake_event) { + amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev); + if (amd_manager) + pm_request_resume(amd_manager->dev); + adata->acp70_sdw0_wake_event = 0; + } + + if (adata->acp70_sdw1_wake_event) { + amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev); + if (amd_manager) + pm_request_resume(amd_manager->dev); + adata->acp70_sdw1_wake_event = 0; + } +} + +static int amd_sof_check_and_handle_acp70_sdw_wake_irq(struct snd_sof_dev *sdev) +{ + const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); + struct acp_dev_data *adata = sdev->pdata->hw_pdata; + u32 ext_intr_stat1; + int irq_flag = 0; + bool sdw_wake_irq = false; + + ext_intr_stat1 = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat1); + if (ext_intr_stat1 & ACP70_SDW0_HOST_WAKE_STAT) { + snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1, + ACP70_SDW0_HOST_WAKE_STAT); + adata->acp70_sdw0_wake_event = true; + sdw_wake_irq = true; + } + + if (ext_intr_stat1 & ACP70_SDW1_HOST_WAKE_STAT) { + snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1, + ACP70_SDW1_HOST_WAKE_STAT); + adata->acp70_sdw1_wake_event = true; + sdw_wake_irq = true; + } + + if (ext_intr_stat1 & ACP70_SDW0_PME_STAT) { + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP70_SW0_WAKE_EN, 0); + snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1, ACP70_SDW0_PME_STAT); + adata->acp70_sdw0_wake_event = true; + sdw_wake_irq = true; + } + + if (ext_intr_stat1 & ACP70_SDW1_PME_STAT) { + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP70_SW1_WAKE_EN, 0); + snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1, ACP70_SDW1_PME_STAT); + adata->acp70_sdw1_wake_event = true; + sdw_wake_irq = true; + } + + if (sdw_wake_irq) { + amd_sof_handle_acp70_sdw_wake_event(adata); + irq_flag = 1; + } + return irq_flag; +} + static irqreturn_t acp_irq_thread(int irq, void *context) { struct snd_sof_dev *sdev = context; @@ -415,7 +481,7 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id) struct acp_dev_data *adata = sdev->pdata->hw_pdata; unsigned int base = desc->dsp_intr_base; unsigned int val; - int irq_flag = 0; + int irq_flag = 0, wake_irq_flag = 0; val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET); if (val & ACP_DSP_TO_HOST_IRQ) { @@ -453,8 +519,14 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id) schedule_work(&amd_manager->amd_sdw_irq_thread); irq_flag = 1; } + switch (adata->pci_rev) { + case ACP70_PCI_ID: + case ACP71_PCI_ID: + wake_irq_flag = amd_sof_check_and_handle_acp70_sdw_wake_irq(sdev); + break; + } } - if (irq_flag) + if (irq_flag || wake_irq_flag) return IRQ_HANDLED; else return IRQ_NONE; @@ -486,6 +558,7 @@ static int acp_power_on(struct snd_sof_dev *sdev) acp_pgfsm_cntl_mask = ACP6X_PGFSM_CNTL_POWER_ON_MASK; break; case ACP70_PCI_ID: + case ACP71_PCI_ID: acp_pgfsm_status_mask = ACP70_PGFSM_STATUS_MASK; acp_pgfsm_cntl_mask = ACP70_PGFSM_CNTL_POWER_ON_MASK; break; @@ -507,7 +580,6 @@ static int acp_power_on(struct snd_sof_dev *sdev) static int acp_reset(struct snd_sof_dev *sdev) { - const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); unsigned int val; int ret; @@ -528,14 +600,6 @@ static int acp_reset(struct snd_sof_dev *sdev) if (ret < 0) dev_err(sdev->dev, "timeout in releasing reset\n"); - if (desc->acp_clkmux_sel) - snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_clkmux_sel, ACP_CLOCK_ACLK); - - if (desc->ext_intr_enb) - snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_enb, 0x01); - - if (desc->ext_intr_cntl) - snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_cntl, ACP_ERROR_IRQ_MASK); return ret; } @@ -566,9 +630,13 @@ static int acp_dsp_reset(struct snd_sof_dev *sdev) static int acp_init(struct snd_sof_dev *sdev) { + const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); + struct acp_dev_data *acp_data; + unsigned int sdw0_wake_en, sdw1_wake_en; int ret; /* power on */ + acp_data = sdev->pdata->hw_pdata; ret = acp_power_on(sdev); if (ret) { dev_err(sdev->dev, "ACP power on failed\n"); @@ -577,7 +645,32 @@ static int acp_init(struct snd_sof_dev *sdev) snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_CONTROL, 0x01); /* Reset */ - return acp_reset(sdev); + ret = acp_reset(sdev); + if (ret) + return ret; + + if (desc->acp_clkmux_sel) + snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_clkmux_sel, ACP_CLOCK_ACLK); + + if (desc->ext_intr_enb) + snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_enb, 0x01); + + if (desc->ext_intr_cntl) + snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_cntl, ACP_ERROR_IRQ_MASK); + + switch (acp_data->pci_rev) { + case ACP70_PCI_ID: + case ACP71_PCI_ID: + sdw0_wake_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP70_SW0_WAKE_EN); + sdw1_wake_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP70_SW1_WAKE_EN); + if (sdw0_wake_en || sdw1_wake_en) + snd_sof_dsp_update_bits(sdev, ACP_DSP_BAR, ACP70_EXTERNAL_INTR_CNTL1, + ACP70_SDW_HOST_WAKE_MASK, ACP70_SDW_HOST_WAKE_MASK); + + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP70_PME_EN, 1); + break; + } + return 0; } static bool check_acp_sdw_enable_status(struct snd_sof_dev *sdev) @@ -616,8 +709,12 @@ int amd_sof_acp_suspend(struct snd_sof_dev *sdev, u32 target_state) dev_err(sdev->dev, "ACP Reset failed\n"); return ret; } - if (acp_data->pci_rev == ACP70_PCI_ID) + switch (acp_data->pci_rev) { + case ACP70_PCI_ID: + case ACP71_PCI_ID: enable = true; + break; + } snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_CONTROL, enable); return 0; @@ -637,9 +734,15 @@ int amd_sof_acp_resume(struct snd_sof_dev *sdev) return ret; } return acp_memory_init(sdev); - } else { - return acp_dsp_reset(sdev); } + switch (acp_data->pci_rev) { + case ACP70_PCI_ID: + case ACP71_PCI_ID: + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP70_PME_EN, 1); + break; + } + + return acp_dsp_reset(sdev); } EXPORT_SYMBOL_NS(amd_sof_acp_resume, "SND_SOC_SOF_AMD_COMMON"); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index d084db34eed8..d3c5b2386cdf 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -74,6 +74,7 @@ #define ACP_RMB_PCI_ID 0x6F #define ACP63_PCI_ID 0x63 #define ACP70_PCI_ID 0x70 +#define ACP71_PCI_ID 0x71 #define HOST_BRIDGE_CZN 0x1630 #define HOST_BRIDGE_VGH 0x1645 @@ -109,9 +110,11 @@ #define ACP_SDW0_IRQ_MASK BIT(21) #define ACP_SDW1_IRQ_MASK BIT(2) #define SDW_ACPI_ADDR_ACP63 5 +#define SDW_ACPI_ADDR_ACP70 SDW_ACPI_ADDR_ACP63 #define ACP_DEFAULT_SRAM_LENGTH 0x00080000 #define ACP_SRAM_PAGE_COUNT 128 #define ACP6X_SDW_MAX_MANAGER_COUNT 2 +#define ACP70_SDW_MAX_MANAGER_COUNT ACP6X_SDW_MAX_MANAGER_COUNT enum clock_source { ACP_CLOCK_96M = 0, @@ -260,6 +263,10 @@ struct acp_dev_data { bool is_dram_in_use; bool is_sram_in_use; bool sdw_en_stat; + /* acp70_sdw0_wake_event flag set to true when wake irq asserted for SW0 instance */ + bool acp70_sdw0_wake_event; + /* acp70_sdw1_wake_event flag set to true when wake irq asserted for SW1 instance */ + bool acp70_sdw1_wake_event; unsigned int pci_rev; }; diff --git a/sound/soc/sof/amd/pci-acp70.c b/sound/soc/sof/amd/pci-acp70.c index 8fa1170a2161..c4db21668252 100644 --- a/sound/soc/sof/amd/pci-acp70.c +++ b/sound/soc/sof/amd/pci-acp70.c @@ -33,12 +33,15 @@ static const struct sof_amd_acp_desc acp70_chip_info = { .ext_intr_cntl = ACP70_EXTERNAL_INTR_CNTL, .ext_intr_stat = ACP70_EXT_INTR_STAT, .ext_intr_stat1 = ACP70_EXT_INTR_STAT1, + .acp_error_stat = ACP70_ERROR_STATUS, .dsp_intr_base = ACP70_DSP_SW_INTR_BASE, .acp_sw0_i2s_err_reason = ACP7X_SW0_I2S_ERROR_REASON, .sram_pte_offset = ACP70_SRAM_PTE_OFFSET, .hw_semaphore_offset = ACP70_AXI2DAGB_SEM_0, .fusion_dsp_offset = ACP70_DSP_FUSION_RUNSTALL, .probe_reg_offset = ACP70_FUTURE_REG_ACLK_0, + .sdw_max_link_count = ACP70_SDW_MAX_MANAGER_COUNT, + .sdw_acpi_dev_addr = SDW_ACPI_ADDR_ACP70, .reg_start_addr = ACP70_REG_START, .reg_end_addr = ACP70_REG_END, }; @@ -70,8 +73,13 @@ static int acp70_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_ { unsigned int flag; - if (pci->revision != ACP70_PCI_ID) + switch (pci->revision) { + case ACP70_PCI_ID: + case ACP71_PCI_ID: + break; + default: return -ENODEV; + } flag = snd_amd_acp_find_config(pci); if (flag != FLAG_AMD_SOF && flag != FLAG_AMD_SOF_ONLY_DMIC) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index aed834d03e10..b11f408f1366 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -607,7 +607,8 @@ static void sof_probe_work(struct work_struct *work) } static void -sof_apply_profile_override(struct sof_loadable_file_profile *path_override) +sof_apply_profile_override(struct sof_loadable_file_profile *path_override, + struct snd_sof_pdata *plat_data) { if (override_ipc_type >= 0 && override_ipc_type < SOF_IPC_TYPE_COUNT) path_override->ipc_type = override_ipc_type; @@ -619,8 +620,11 @@ sof_apply_profile_override(struct sof_loadable_file_profile *path_override) path_override->fw_lib_path = override_lib_path; if (override_tplg_path) path_override->tplg_path = override_tplg_path; - if (override_tplg_filename) + if (override_tplg_filename) { path_override->tplg_name = override_tplg_filename; + /* User requested a specific topology file and expect it to be loaded */ + plat_data->disable_function_topology = true; + } } int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) @@ -654,7 +658,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) } } - sof_apply_profile_override(&plat_data->ipc_file_profile_base); + sof_apply_profile_override(&plat_data->ipc_file_profile_base, plat_data); /* Initialize sof_ops based on the initial selected IPC version */ ret = sof_init_sof_ops(sdev); diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index ab07512e511d..a40a8047873e 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -11,6 +11,7 @@ #include <linux/arm-smccc.h> #include <linux/firmware/imx/svc/misc.h> #include <linux/mfd/syscon.h> +#include <linux/reset.h> #include "imx-common.h" @@ -23,13 +24,6 @@ #define IMX8M_DAP_PWRCTL (0x4000 + 0x3020) #define IMX8M_PWRCTL_CORERESET BIT(16) -#define AudioDSP_REG0 0x100 -#define AudioDSP_REG1 0x104 -#define AudioDSP_REG2 0x108 -#define AudioDSP_REG3 0x10c - -#define AudioDSP_REG2_RUNSTALL BIT(5) - /* imx8ulp macros */ #define FSL_SIP_HIFI_XRDC 0xc200000e #define SYSCTRL0 0x8 @@ -43,6 +37,7 @@ struct imx8m_chip_data { void __iomem *dap; struct regmap *regmap; + struct reset_control *run_stall; }; /* @@ -137,8 +132,7 @@ static int imx8m_reset(struct snd_sof_dev *sdev) /* keep reset asserted for 10 cycles */ usleep_range(1, 2); - regmap_update_bits(chip->regmap, AudioDSP_REG2, - AudioDSP_REG2_RUNSTALL, AudioDSP_REG2_RUNSTALL); + reset_control_assert(chip->run_stall); /* take the DSP out of reset and keep stalled for FW loading */ pwrctl = readl(chip->dap + IMX8M_DAP_PWRCTL); @@ -152,9 +146,7 @@ static int imx8m_run(struct snd_sof_dev *sdev) { struct imx8m_chip_data *chip = get_chip_pdata(sdev); - regmap_update_bits(chip->regmap, AudioDSP_REG2, AudioDSP_REG2_RUNSTALL, 0); - - return 0; + return reset_control_deassert(chip->run_stall); } static int imx8m_probe(struct snd_sof_dev *sdev) @@ -174,10 +166,10 @@ static int imx8m_probe(struct snd_sof_dev *sdev) return dev_err_probe(sdev->dev, -ENODEV, "failed to ioremap DAP\n"); - chip->regmap = syscon_regmap_lookup_by_phandle(sdev->dev->of_node, "fsl,dsp-ctrl"); - if (IS_ERR(chip->regmap)) - return dev_err_probe(sdev->dev, PTR_ERR(chip->regmap), - "failed to fetch dsp ctrl regmap\n"); + chip->run_stall = devm_reset_control_get_exclusive(sdev->dev, "runstall"); + if (IS_ERR(chip->run_stall)) + return dev_err_probe(sdev->dev, PTR_ERR(chip->run_stall), + "failed to get dsp runstall reset control\n"); common->chip_pdata = chip; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 108cad04879e..e14f82c0831f 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -935,6 +935,7 @@ extern const struct sof_intel_dsp_desc mtl_chip_info; extern const struct sof_intel_dsp_desc arl_s_chip_info; extern const struct sof_intel_dsp_desc lnl_chip_info; extern const struct sof_intel_dsp_desc ptl_chip_info; +extern const struct sof_intel_dsp_desc wcl_chip_info; /* Probes support */ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) diff --git a/sound/soc/sof/intel/pci-ptl.c b/sound/soc/sof/intel/pci-ptl.c index 7d4c46f56931..68f6a9841633 100644 --- a/sound/soc/sof/intel/pci-ptl.c +++ b/sound/soc/sof/intel/pci-ptl.c @@ -55,10 +55,40 @@ static const struct sof_dev_desc ptl_desc = { .ops_init = sof_ptl_ops_init, }; +static const struct sof_dev_desc wcl_desc = { + .use_acpi_target_states = true, + .machines = snd_soc_acpi_intel_ptl_machines, + .alt_machines = snd_soc_acpi_intel_ptl_sdw_machines, + .resindex_lpe_base = 0, + .resindex_pcicfg_base = -1, + .resindex_imr_base = -1, + .irqindex_host_ipc = -1, + .chip_info = &wcl_chip_info, + .ipc_supported_mask = BIT(SOF_IPC_TYPE_4), + .ipc_default = SOF_IPC_TYPE_4, + .dspless_mode_supported = true, + .default_fw_path = { + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/wcl", + }, + .default_lib_path = { + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/wcl", + }, + .default_tplg_path = { + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", + }, + .default_fw_filename = { + [SOF_IPC_TYPE_4] = "sof-wcl.ri", + }, + .nocodec_tplg_filename = "sof-ptl-nocodec.tplg", + .ops = &sof_ptl_ops, + .ops_init = sof_ptl_ops_init, +}; + /* PCI IDs */ static const struct pci_device_id sof_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, HDA_PTL, &ptl_desc) }, /* PTL */ { PCI_DEVICE_DATA(INTEL, HDA_PTL_H, &ptl_desc) }, /* PTL-H */ + { PCI_DEVICE_DATA(INTEL, HDA_WCL, &wcl_desc) }, /* WCL */ { 0, } }; MODULE_DEVICE_TABLE(pci, sof_pci_ids); diff --git a/sound/soc/sof/intel/ptl.c b/sound/soc/sof/intel/ptl.c index aa0b772178bc..875d18193b05 100644 --- a/sound/soc/sof/intel/ptl.c +++ b/sound/soc/sof/intel/ptl.c @@ -126,6 +126,29 @@ const struct sof_intel_dsp_desc ptl_chip_info = { .hw_ip_version = SOF_INTEL_ACE_3_0, }; +const struct sof_intel_dsp_desc wcl_chip_info = { + .cores_num = 3, + .init_core_mask = BIT(0), + .host_managed_cores_mask = BIT(0), + .ipc_req = MTL_DSP_REG_HFIPCXIDR, + .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY, + .ipc_ack = MTL_DSP_REG_HFIPCXIDA, + .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, + .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, + .rom_status_reg = LNL_DSP_REG_HFDSC, + .rom_init_timeout = 300, + .ssp_count = MTL_SSP_COUNT, + .d0i3_offset = MTL_HDA_VS_D0I3C, + .read_sdw_lcount = hda_sdw_check_lcount_ext, + .check_sdw_irq = lnl_dsp_check_sdw_irq, + .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, + .check_ipc_irq = mtl_dsp_check_ipc_irq, + .cl_init = mtl_dsp_cl_init, + .power_down_dsp = mtl_power_down_dsp, + .disable_interrupts = lnl_dsp_disable_interrupts, + .hw_ip_version = SOF_INTEL_ACE_3_0, +}; + MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_LNL"); MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK"); diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index c09b424ab863..8eee3e1aadf9 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -784,7 +784,8 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm /* allocate memory for max number of pipeline IDs */ pipeline_list->pipelines = kcalloc(ipc4_data->max_num_pipelines, - sizeof(struct snd_sof_widget *), GFP_KERNEL); + sizeof(*pipeline_list->pipelines), + GFP_KERNEL); if (!pipeline_list->pipelines) { sof_ipc4_pcm_free(sdev, spcm); return -ENOMEM; diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 2fc14b9a33d4..c50249aadea9 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -216,7 +216,7 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) if (ret < 0) return ret; - ret = pci_request_regions(pci, "Audio DSP"); + ret = pcim_request_all_regions(pci, "Audio DSP"); if (ret < 0) return ret; @@ -240,8 +240,7 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) path_override->ipc_type = sof_pci_ipc_type; } else { dev_err(dev, "Invalid IPC type requested: %d\n", sof_pci_ipc_type); - ret = -EINVAL; - goto out; + return -EINVAL; } path_override->fw_path = fw_path; @@ -271,13 +270,7 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) sof_pdata->sof_probe_complete = sof_pci_probe_complete; /* call sof helper for DSP hardware probe */ - ret = snd_sof_device_probe(dev, sof_pdata); - -out: - if (ret) - pci_release_regions(pci); - - return ret; + return snd_sof_device_probe(dev, sof_pdata); } EXPORT_SYMBOL_NS(sof_pci_probe, "SND_SOC_SOF_PCI_DEV"); @@ -290,9 +283,6 @@ void sof_pci_remove(struct pci_dev *pci) if (snd_sof_device_probe_completed(&pci->dev) && !(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME)) pm_runtime_get_noresume(&pci->dev); - - /* release pci regions and disable device */ - pci_release_regions(pci); } EXPORT_SYMBOL_NS(sof_pci_remove, "SND_SOC_SOF_PCI_DEV"); diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 14aa8ecc4bc4..d612d693efc3 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -19,6 +19,10 @@ #include "sof-audio.h" #include "ops.h" +static bool disable_function_topology; +module_param(disable_function_topology, bool, 0444); +MODULE_PARM_DESC(disable_function_topology, "Disable function topology loading"); + #define COMP_ID_UNASSIGNED 0xffffffff /* * Constants used in the computation of linear volume gain @@ -571,7 +575,11 @@ static int sof_copy_tuples(struct snd_sof_dev *sdev, struct snd_soc_tplg_vendor_ continue; tuples[*num_copied_tuples].token = tokens[j].token; - tuples[*num_copied_tuples].value.s = elem->string; + tuples[*num_copied_tuples].value.s = + devm_kasprintf(sdev->dev, GFP_KERNEL, + "%s", elem->string); + if (!tuples[*num_copied_tuples].value.s) + return -ENOMEM; } else { struct snd_soc_tplg_vendor_value_elem *elem; @@ -2316,8 +2324,10 @@ static const struct snd_soc_tplg_ops sof_tplg_ops = { .link_load = sof_link_load, .link_unload = sof_link_unload, - /* completion - called at completion of firmware loading */ - .complete = sof_complete, + /* + * No need to set the complete callback. sof_complete will be called explicitly after + * topology loading is complete. + */ /* manifest - optional to inform component of manifest */ .manifest = sof_manifest, @@ -2473,36 +2483,83 @@ static const struct snd_soc_tplg_ops sof_dspless_tplg_ops = { int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_sof_pdata *sof_pdata = sdev->pdata; + const char *tplg_filename_prefix = sof_pdata->tplg_filename_prefix; const struct firmware *fw; + const char **tplg_files; + int tplg_cnt = 0; int ret; + int i; - dev_dbg(scomp->dev, "loading topology:%s\n", file); + tplg_files = kcalloc(scomp->card->num_links, sizeof(char *), GFP_KERNEL); + if (!tplg_files) + return -ENOMEM; - ret = request_firmware(&fw, file, scomp->dev); - if (ret < 0) { - dev_err(scomp->dev, "error: tplg request firmware %s failed err: %d\n", - file, ret); - dev_err(scomp->dev, - "you may need to download the firmware from https://github.com/thesofproject/sof-bin/\n"); - return ret; + if (!sof_pdata->disable_function_topology && !disable_function_topology && + sof_pdata->machine && sof_pdata->machine->get_function_tplg_files) { + tplg_cnt = sof_pdata->machine->get_function_tplg_files(scomp->card, + sof_pdata->machine, + tplg_filename_prefix, + &tplg_files); + if (tplg_cnt < 0) { + kfree(tplg_files); + return tplg_cnt; + } } - if (sdev->dspless_mode_selected) - ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw); - else - ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw); + /* + * The monolithic topology will be used if there is no get_function_tplg_files + * callback or the callback returns 0. + */ + if (!tplg_cnt) { + tplg_files[0] = file; + tplg_cnt = 1; + dev_dbg(scomp->dev, "loading topology: %s\n", file); + } else { + dev_info(scomp->dev, "Using function topologies instead %s\n", file); + } - if (ret < 0) { - dev_err(scomp->dev, "error: tplg component load failed %d\n", - ret); - ret = -EINVAL; + for (i = 0; i < tplg_cnt; i++) { + /* Only print the file names if the function topologies are used */ + if (tplg_files[0] != file) + dev_info(scomp->dev, "loading topology %d: %s\n", i, tplg_files[i]); + + ret = request_firmware(&fw, tplg_files[i], scomp->dev); + if (ret < 0) { + /* + * snd_soc_tplg_component_remove(scomp) will be called + * if snd_soc_tplg_component_load(scomp) failed and all + * objects in the scomp will be removed. No need to call + * snd_soc_tplg_component_remove(scomp) here. + */ + dev_err(scomp->dev, "tplg request firmware %s failed err: %d\n", + tplg_files[i], ret); + goto out; + } + + if (sdev->dspless_mode_selected) + ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw); + else + ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw); + + release_firmware(fw); + + if (ret < 0) { + dev_err(scomp->dev, "tplg %s component load failed %d\n", + tplg_files[i], ret); + goto out; + } } - release_firmware(fw); + /* call sof_complete when topologies are loaded successfully */ + ret = sof_complete(scomp); +out: if (ret >= 0 && sdev->led_present) ret = snd_ctl_led_request(); + kfree(tplg_files); + return ret; } EXPORT_SYMBOL(snd_sof_load_topology); |