diff options
Diffstat (limited to 'sound/soc/intel/avs')
38 files changed, 833 insertions, 157 deletions
diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile index 5139a019a4ad..576dc0da381d 100644 --- a/sound/soc/intel/avs/Makefile +++ b/sound/soc/intel/avs/Makefile @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only snd-soc-avs-y := dsp.o ipc.o messages.o utils.o core.o loader.o \ - topology.o path.o pcm.o board_selection.o control.o \ - sysfs.o + topology.o path.o pcm.o board_selection.o control.o \ + sysfs.o snd-soc-avs-y += cldma.o -snd-soc-avs-y += skl.o apl.o cnl.o icl.o tgl.o +snd-soc-avs-y += skl.o apl.o cnl.o icl.o tgl.o mtl.o lnl.o ptl.o snd-soc-avs-y += trace.o # tell define_trace.h where to find the trace header diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index ec5502f9d5cb..4c096afc5848 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -69,6 +69,7 @@ extern const struct avs_dsp_ops avs_apl_dsp_ops; extern const struct avs_dsp_ops avs_cnl_dsp_ops; extern const struct avs_dsp_ops avs_icl_dsp_ops; extern const struct avs_dsp_ops avs_tgl_dsp_ops; +extern const struct avs_dsp_ops avs_ptl_dsp_ops; #define AVS_PLATATTR_CLDMA BIT_ULL(0) #define AVS_PLATATTR_IMR BIT_ULL(1) @@ -267,8 +268,14 @@ void avs_ipc_block(struct avs_ipc *ipc); int avs_dsp_disable_d0ix(struct avs_dev *adev); int avs_dsp_enable_d0ix(struct avs_dev *adev); +int avs_mtl_core_power(struct avs_dev *adev, u32 core_mask, bool power); +int avs_mtl_core_reset(struct avs_dev *adev, u32 core_mask, bool power); +int avs_mtl_core_stall(struct avs_dev *adev, u32 core_mask, bool stall); +int avs_lnl_core_stall(struct avs_dev *adev, u32 core_mask, bool stall); +void avs_mtl_interrupt_control(struct avs_dev *adev, bool enable); void avs_skl_ipc_interrupt(struct avs_dev *adev); irqreturn_t avs_cnl_dsp_interrupt(struct avs_dev *adev); +irqreturn_t avs_mtl_dsp_interrupt(struct avs_dev *adev); int avs_apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, u32 fifo_full_period, unsigned long resource_mask, u32 *priorities); int avs_icl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, @@ -342,7 +349,7 @@ struct avs_soc_component { extern const struct snd_soc_dai_ops avs_dai_fe_ops; int avs_soc_component_register(struct device *dev, const char *name, - const struct snd_soc_component_driver *drv, + struct snd_soc_component_driver *drv, struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais); int avs_dmic_platform_register(struct avs_dev *adev, const char *name); int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned long port_mask, diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c index 2d706edcbf92..673ccf162023 100644 --- a/sound/soc/intel/avs/board_selection.c +++ b/sound/soc/intel/avs/board_selection.c @@ -17,10 +17,15 @@ #include <sound/soc-acpi.h> #include <sound/soc-component.h> #include "avs.h" +#include "utils.h" -static bool i2s_test; -module_param(i2s_test, bool, 0444); -MODULE_PARM_DESC(i2s_test, "Probe I2S test-board and skip all other I2S boards"); +static char *i2s_test; +module_param(i2s_test, charp, 0444); +MODULE_PARM_DESC(i2s_test, "Use I2S test-board instead of ACPI, i2s_test=ssp0tdm,ssp1tdm,... 0 to ignore port"); + +bool obsolete_card_names = IS_ENABLED(CONFIG_SND_SOC_INTEL_AVS_CARDNAME_OBSOLETE); +module_param_named(obsolete_card_names, obsolete_card_names, bool, 0444); +MODULE_PARM_DESC(obsolete_card_names, "Use obsolete card names 0=no, 1=yes"); static const struct dmi_system_id kbl_dmi_table[] = { { @@ -141,7 +146,7 @@ static struct snd_soc_acpi_mach avs_kbl_i2s_machines[] = { .mach_params = { .i2s_link_mask = AVS_SSP(0), }, - .pdata = (unsigned long[]){ 0x2, 0, 0, 0, 0, 0 }, /* SSP0 TDMs */ + .pdata = (struct avs_mach_pdata[]){ { .tdms = (unsigned long[]){ 0x2 } } }, .tplg_filename = "rt5514-tplg.bin", }, { @@ -202,7 +207,9 @@ static struct snd_soc_acpi_mach avs_apl_i2s_machines[] = { .mach_params = { .i2s_link_mask = AVS_SSP_RANGE(0, 5), }, - .pdata = (unsigned long[]){ 0x1, 0x1, 0x14, 0x1, 0x1, 0x1 }, /* SSP2 TDMs */ + .pdata = (struct avs_mach_pdata[]){ { + .tdms = (unsigned long[]){ 0x1, 0x1, 0x14, 0x1, 0x1, 0x1 } + } }, .tplg_filename = "tdf8532-tplg.bin", }, { @@ -324,52 +331,6 @@ static struct snd_soc_acpi_mach avs_mbl_i2s_machines[] = { {} }; -static struct snd_soc_acpi_mach avs_test_i2s_machines[] = { - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(0), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(1), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(2), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(3), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(4), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - { - .drv_name = "avs_i2s_test", - .mach_params = { - .i2s_link_mask = AVS_SSP(5), - }, - .tplg_filename = "i2s-test-tplg.bin", - }, - /* no NULL terminator, as we depend on ARRAY SIZE due to .id == NULL */ -}; - struct avs_acpi_boards { int id; struct snd_soc_acpi_mach *machs; @@ -394,7 +355,8 @@ static const struct avs_acpi_boards i2s_boards[] = { AVS_MACH_ENTRY(HDA_ADL_P, avs_tgl_i2s_machines), AVS_MACH_ENTRY(HDA_RPL_P_0, avs_tgl_i2s_machines), AVS_MACH_ENTRY(HDA_RPL_M, avs_mbl_i2s_machines), - {} + AVS_MACH_ENTRY(HDA_FCL, avs_tgl_i2s_machines), + { }, }; static const struct avs_acpi_boards *avs_get_i2s_boards(struct avs_dev *adev) @@ -445,6 +407,7 @@ static int avs_register_dmic_board(struct avs_dev *adev) { struct platform_device *codec, *board; struct snd_soc_acpi_mach mach = {{0}}; + struct avs_mach_pdata *pdata; int ret; if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1)) { @@ -468,6 +431,11 @@ static int avs_register_dmic_board(struct avs_dev *adev) if (ret < 0) return ret; + pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + pdata->obsolete_card_names = obsolete_card_names; + mach.pdata = pdata; mach.tplg_filename = "dmic-tplg.bin"; mach.mach_params.platform = "dmic-platform"; @@ -490,9 +458,11 @@ static int avs_register_dmic_board(struct avs_dev *adev) static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach) { struct platform_device *board; + struct avs_mach_pdata *pdata; int num_ssps; char *name; int ret; + int uid; num_ssps = adev->hw_cfg.i2s_caps.ctrl_count; if (fls(mach->mach_params.i2s_link_mask) > num_ssps) { @@ -502,18 +472,29 @@ static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach return -ENODEV; } - name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s.%d-platform", mach->drv_name, - mach->mach_params.i2s_link_mask); + pdata = mach->pdata; + if (!pdata) + pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + pdata->obsolete_card_names = obsolete_card_names; + mach->pdata = pdata; + + uid = mach->mach_params.i2s_link_mask; + if (avs_mach_singular_ssp(mach)) + uid = (uid << AVS_CHANNELS_MAX) + avs_mach_ssp_tdm(mach, avs_mach_ssp_port(mach)); + + name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s.%d-platform", mach->drv_name, uid); if (!name) return -ENOMEM; - ret = avs_i2s_platform_register(adev, name, mach->mach_params.i2s_link_mask, mach->pdata); + ret = avs_i2s_platform_register(adev, name, mach->mach_params.i2s_link_mask, pdata->tdms); if (ret < 0) return ret; mach->mach_params.platform = name; - board = platform_device_register_data(NULL, mach->drv_name, mach->mach_params.i2s_link_mask, + board = platform_device_register_data(NULL, mach->drv_name, uid, (const void *)mach, sizeof(*mach)); if (IS_ERR(board)) { dev_err(adev->dev, "ssp board register failed\n"); @@ -529,35 +510,82 @@ static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach return 0; } -static int avs_register_i2s_boards(struct avs_dev *adev) +static int avs_register_i2s_test_board(struct avs_dev *adev, int ssp_port, int tdm_slot) { - const struct avs_acpi_boards *boards; struct snd_soc_acpi_mach *mach; + int tdm_mask = BIT(tdm_slot); + unsigned long *tdm_cfg; + char *tplg_name; int ret; - if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_SSP, -1, -1, -1)) { - dev_dbg(adev->dev, "no I2S endpoints present\n"); - return 0; + mach = devm_kzalloc(adev->dev, sizeof(*mach), GFP_KERNEL); + tdm_cfg = devm_kcalloc(adev->dev, ssp_port + 1, sizeof(unsigned long), GFP_KERNEL); + tplg_name = devm_kasprintf(adev->dev, GFP_KERNEL, AVS_STRING_FMT("i2s", "-test-tplg.bin", + ssp_port, tdm_slot)); + if (!mach || !tdm_cfg || !tplg_name) + return -ENOMEM; + + mach->drv_name = "avs_i2s_test"; + mach->mach_params.i2s_link_mask = AVS_SSP(ssp_port); + tdm_cfg[ssp_port] = tdm_mask; + mach->pdata = tdm_cfg; + mach->tplg_filename = tplg_name; + + ret = avs_register_i2s_board(adev, mach); + if (ret < 0) { + dev_warn(adev->dev, "register i2s %s failed: %d\n", mach->drv_name, ret); + return ret; } - if (i2s_test) { - int i, num_ssps; + return 0; +} - num_ssps = adev->hw_cfg.i2s_caps.ctrl_count; - /* constrain just in case FW says there can be more SSPs than possible */ - num_ssps = min_t(int, ARRAY_SIZE(avs_test_i2s_machines), num_ssps); +static int avs_register_i2s_test_boards(struct avs_dev *adev) +{ + int max_ssps = adev->hw_cfg.i2s_caps.ctrl_count; + int ssp_port, tdm_slot, ret; + unsigned long tdm_slots; + u32 *array, num_elems; + + ret = parse_int_array(i2s_test, strlen(i2s_test), (int **)&array); + if (ret) { + dev_err(adev->dev, "failed to parse i2s_test parameter\n"); + return ret; + } - mach = avs_test_i2s_machines; + num_elems = *array; + if (num_elems > max_ssps) { + dev_err(adev->dev, "board supports only %d SSP, %d specified\n", + max_ssps, num_elems); + return -EINVAL; + } - for (i = 0; i < num_ssps; i++) { - ret = avs_register_i2s_board(adev, &mach[i]); - if (ret < 0) - dev_warn(adev->dev, "register i2s %s failed: %d\n", mach->drv_name, - ret); + for (ssp_port = 0; ssp_port < num_elems; ssp_port++) { + tdm_slots = array[1 + ssp_port]; + for_each_set_bit(tdm_slot, &tdm_slots, 16) { + ret = avs_register_i2s_test_board(adev, ssp_port, tdm_slot); + if (ret) + return ret; } + } + + return 0; +} + +static int avs_register_i2s_boards(struct avs_dev *adev) +{ + const struct avs_acpi_boards *boards; + struct snd_soc_acpi_mach *mach; + int ret; + + if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_SSP, -1, -1, -1)) { + dev_dbg(adev->dev, "no I2S endpoints present\n"); return 0; } + if (i2s_test) + return avs_register_i2s_test_boards(adev); + boards = avs_get_i2s_boards(adev); if (!boards) { dev_dbg(adev->dev, "no I2S endpoints supported\n"); @@ -584,6 +612,7 @@ static int avs_register_hda_board(struct avs_dev *adev, struct hda_codec *codec) { struct snd_soc_acpi_mach mach = {{0}}; struct platform_device *board; + struct avs_mach_pdata *pdata; struct hdac_device *hdev = &codec->core; char *pname; int ret, id; @@ -592,11 +621,17 @@ static int avs_register_hda_board(struct avs_dev *adev, struct hda_codec *codec) if (!pname) return -ENOMEM; + pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + pdata->obsolete_card_names = obsolete_card_names; + pdata->codec = codec; + ret = avs_hda_platform_register(adev, pname); if (ret < 0) return ret; - mach.pdata = codec; + mach.pdata = pdata; mach.mach_params.platform = pname; mach.tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL, "hda-%08x-tplg.bin", hdev->vendor_id); diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index ba4bee42124c..8b654181004e 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -4,6 +4,14 @@ menu "Intel AVS Machine drivers" comment "Available DSP configurations" +config SND_SOC_INTEL_AVS_CARDNAME_OBSOLETE + bool "Use obsolete card names" + default n + help + Use obsolete names for some of avs cards. This option should be + used if your system depends on old card names, for example having + not up to date UCM files. + config SND_SOC_INTEL_AVS_MACH_DA7219 tristate "da7219 I2S board" depends on I2C diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c index 7217ae51e89c..3ef0db254142 100644 --- a/sound/soc/intel/avs/boards/da7219.c +++ b/sound/soc/intel/avs/boards/da7219.c @@ -214,6 +214,7 @@ static int avs_da7219_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; @@ -222,6 +223,7 @@ static int avs_da7219_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -238,7 +240,12 @@ static int avs_da7219_probe(struct platform_device *pdev) if (!jack || !card) return -ENOMEM; - card->name = "avs_da7219"; + if (pdata->obsolete_card_names) { + card->name = "avs_da7219"; + } else { + card->driver_name = "avs_da7219"; + card->long_name = card->name = "AVS I2S DA7219"; + } card->dev = dev; card->owner = THIS_MODULE; card->dai_link = dai_link; @@ -256,7 +263,7 @@ static int avs_da7219_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_da7219_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/dmic.c b/sound/soc/intel/avs/boards/dmic.c index 4dd9591ee98b..a1448a98874d 100644 --- a/sound/soc/intel/avs/boards/dmic.c +++ b/sound/soc/intel/avs/boards/dmic.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include "../utils.h" SND_SOC_DAILINK_DEF(dmic_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); SND_SOC_DAILINK_DEF(dmic_wov_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC WoV Pin"))); @@ -49,17 +50,24 @@ static const struct snd_soc_dapm_route card_routes[] = { static int avs_dmic_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; int ret; mach = dev_get_platdata(dev); + pdata = mach->pdata; card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; - card->name = "avs_dmic"; + if (pdata->obsolete_card_names) { + card->name = "avs_dmic"; + } else { + card->driver_name = "avs_dmic"; + card->long_name = card->name = "AVS DMIC"; + } card->dev = dev; card->owner = THIS_MODULE; card->dai_link = card_dai_links; @@ -74,7 +82,7 @@ static int avs_dmic_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_dmic_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c index 6f3c4f6c9302..1955f2d383c5 100644 --- a/sound/soc/intel/avs/boards/es8336.c +++ b/sound/soc/intel/avs/boards/es8336.c @@ -259,6 +259,7 @@ static int avs_es8336_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct avs_card_drvdata *data; struct snd_soc_card *card; struct device *dev = &pdev->dev; @@ -267,6 +268,7 @@ static int avs_es8336_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -283,7 +285,12 @@ static int avs_es8336_probe(struct platform_device *pdev) if (!data || !card) return -ENOMEM; - card->name = "avs_es8336"; + if (pdata->obsolete_card_names) { + card->name = "avs_es8336"; + } else { + card->driver_name = "avs_es8336"; + card->long_name = card->name = "AVS I2S ES8336"; + } card->dev = dev; card->owner = THIS_MODULE; card->suspend_pre = avs_card_suspend_pre; @@ -303,7 +310,7 @@ static int avs_es8336_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_es8336_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c index cb6d54db7189..19b2255a8ac3 100644 --- a/sound/soc/intel/avs/boards/hdaudio.c +++ b/sound/soc/intel/avs/boards/hdaudio.c @@ -13,6 +13,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include "../../../codecs/hda.h" +#include "../utils.h" static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int pcm_count, const char *platform_name, struct snd_soc_dai_link **links) @@ -95,7 +96,8 @@ avs_card_hdmi_pcm_at(struct snd_soc_card *card, int hdmi_idx) static int avs_card_late_probe(struct snd_soc_card *card) { struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); - struct hda_codec *codec = mach->pdata; + struct avs_mach_pdata *pdata = mach->pdata; + struct hda_codec *codec = pdata->codec; struct hda_pcm *hpcm; /* Topology pcm indexing is 1-based */ int i = 1; @@ -124,6 +126,7 @@ static int avs_card_late_probe(struct snd_soc_card *card) static int avs_probing_link_init(struct snd_soc_pcm_runtime *rtm) { struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_dai_link *links = NULL; struct snd_soc_card *card = rtm->card; struct hda_codec *codec; @@ -131,7 +134,8 @@ static int avs_probing_link_init(struct snd_soc_pcm_runtime *rtm) int ret, pcm_count = 0; mach = dev_get_platdata(card->dev); - codec = mach->pdata; + pdata = mach->pdata; + codec = pdata->codec; if (list_empty(&codec->pcm_list_head)) return -EINVAL; @@ -167,12 +171,14 @@ static int avs_hdaudio_probe(struct platform_device *pdev) { struct snd_soc_dai_link *binder; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; struct hda_codec *codec; mach = dev_get_platdata(dev); - codec = mach->pdata; + pdata = mach->pdata; + codec = pdata->codec; /* codec may be unloaded before card's probe() fires */ if (!device_is_registered(&codec->core.dev)) @@ -200,7 +206,16 @@ static int avs_hdaudio_probe(struct platform_device *pdev) if (!card) return -ENOMEM; - card->name = binder->codecs->name; + if (pdata->obsolete_card_names) { + card->name = binder->codecs->name; + } else { + card->driver_name = "avs_hdaudio"; + if (hda_codec_is_display(codec)) + card->long_name = card->name = "AVS HDMI"; + else + card->long_name = card->name = "AVS HD-Audio"; + } + card->dev = dev; card->owner = THIS_MODULE; card->dai_link = binder; @@ -209,7 +224,7 @@ static int avs_hdaudio_probe(struct platform_device *pdev) if (hda_codec_is_display(codec)) card->late_probe = avs_card_late_probe; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_hdaudio_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/i2s_test.c b/sound/soc/intel/avs/boards/i2s_test.c index 4556f105c793..f7b6d7715738 100644 --- a/sound/soc/intel/avs/boards/i2s_test.c +++ b/sound/soc/intel/avs/boards/i2s_test.c @@ -56,6 +56,7 @@ static int avs_i2s_test_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; @@ -63,6 +64,7 @@ static int avs_i2s_test_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; if (!avs_mach_singular_ssp(mach)) { dev_err(dev, "Invalid SSP configuration\n"); @@ -80,8 +82,15 @@ static int avs_i2s_test_probe(struct platform_device *pdev) if (!card) return -ENOMEM; - card->name = devm_kasprintf(dev, GFP_KERNEL, - AVS_STRING_FMT("ssp", "-loopback", ssp_port, tdm_slot)); + if (pdata->obsolete_card_names) { + card->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("ssp", "-loopback", ssp_port, tdm_slot)); + } else { + card->driver_name = "avs_i2s_test"; + card->long_name = card->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("AVS I2S TEST-", "", + ssp_port, tdm_slot)); + } if (!card->name) return -ENOMEM; @@ -101,7 +110,7 @@ static int avs_i2s_test_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_i2s_test_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c index c55c1d60b777..72053f83e98b 100644 --- a/sound/soc/intel/avs/boards/max98357a.c +++ b/sound/soc/intel/avs/boards/max98357a.c @@ -93,6 +93,7 @@ static int avs_max98357a_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; @@ -100,6 +101,7 @@ static int avs_max98357a_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -115,7 +117,12 @@ static int avs_max98357a_probe(struct platform_device *pdev) if (!card) return -ENOMEM; - card->name = "avs_max98357a"; + if (pdata->obsolete_card_names) { + card->name = "avs_max98357a"; + } else { + card->driver_name = "avs_max98357a"; + card->long_name = card->name = "AVS I2S MAX98357A"; + } card->dev = dev; card->owner = THIS_MODULE; card->dai_link = dai_link; @@ -132,7 +139,7 @@ static int avs_max98357a_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_max98357a_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/max98373.c b/sound/soc/intel/avs/boards/max98373.c index 970f82bf4ce8..cdba1c3ee20b 100644 --- a/sound/soc/intel/avs/boards/max98373.c +++ b/sound/soc/intel/avs/boards/max98373.c @@ -146,6 +146,7 @@ static int avs_max98373_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; @@ -153,6 +154,7 @@ static int avs_max98373_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -168,7 +170,12 @@ static int avs_max98373_probe(struct platform_device *pdev) if (!card) return -ENOMEM; - card->name = "avs_max98373"; + if (pdata->obsolete_card_names) { + card->name = "avs_max98373"; + } else { + card->driver_name = "avs_max98373"; + card->long_name = card->name = "AVS I2S MAX98373"; + } card->dev = dev; card->owner = THIS_MODULE; card->dai_link = dai_link; @@ -187,7 +194,7 @@ static int avs_max98373_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_max98373_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c index e4ce553bf1d6..a68e227044c5 100644 --- a/sound/soc/intel/avs/boards/max98927.c +++ b/sound/soc/intel/avs/boards/max98927.c @@ -143,6 +143,7 @@ static int avs_max98927_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; @@ -150,6 +151,7 @@ static int avs_max98927_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -165,7 +167,12 @@ static int avs_max98927_probe(struct platform_device *pdev) if (!card) return -ENOMEM; - card->name = "avs_max98927"; + if (pdata->obsolete_card_names) { + card->name = "avs_max98927"; + } else { + card->driver_name = "avs_max98927"; + card->long_name = card->name = "AVS I2S MAX98927"; + } card->dev = dev; card->owner = THIS_MODULE; card->dai_link = dai_link; @@ -184,7 +191,7 @@ static int avs_max98927_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_max98927_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c index e203ceb83b87..3fb1a5d07ae1 100644 --- a/sound/soc/intel/avs/boards/nau8825.c +++ b/sound/soc/intel/avs/boards/nau8825.c @@ -246,6 +246,7 @@ static int avs_nau8825_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; @@ -254,6 +255,7 @@ static int avs_nau8825_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -270,7 +272,12 @@ static int avs_nau8825_probe(struct platform_device *pdev) if (!jack || !card) return -ENOMEM; - card->name = "avs_nau8825"; + if (pdata->obsolete_card_names) { + card->name = "avs_nau8825"; + } else { + card->driver_name = "avs_nau8825"; + card->long_name = card->name = "AVS I2S NAU8825"; + } card->dev = dev; card->owner = THIS_MODULE; card->suspend_pre = avs_card_suspend_pre; @@ -290,7 +297,7 @@ static int avs_nau8825_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_nau8825_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/pcm3168a.c b/sound/soc/intel/avs/boards/pcm3168a.c index 5d0e7a5bdc74..b5bebadbbcb2 100644 --- a/sound/soc/intel/avs/boards/pcm3168a.c +++ b/sound/soc/intel/avs/boards/pcm3168a.c @@ -11,6 +11,8 @@ #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "../utils.h" static const struct snd_soc_dapm_widget card_widgets[] = { SND_SOC_DAPM_HP("CPB Stereo HP 1", NULL), @@ -95,10 +97,15 @@ static int avs_create_dai_links(struct device *dev, struct snd_soc_dai_link **li static int avs_pcm3168a_probe(struct platform_device *pdev) { + struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct device *dev = &pdev->dev; struct snd_soc_card *card; int ret; + mach = dev_get_platdata(dev); + pdata = mach->pdata; + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; @@ -107,7 +114,12 @@ static int avs_pcm3168a_probe(struct platform_device *pdev) if (ret) return ret; - card->name = "avs_pcm3168a"; + if (pdata->obsolete_card_names) { + card->name = "avs_pcm3168a"; + } else { + card->driver_name = "avs_pcm3168a"; + card->long_name = card->name = "AVS I2S PCM3168A"; + } card->dev = dev; card->owner = THIS_MODULE; card->dapm_widgets = card_widgets; @@ -116,7 +128,7 @@ static int avs_pcm3168a_probe(struct platform_device *pdev) card->num_dapm_routes = ARRAY_SIZE(card_routes); card->fully_routed = true; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_pcm3168a_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/probe.c b/sound/soc/intel/avs/boards/probe.c index 1cdc285ab810..06c1f19f27aa 100644 --- a/sound/soc/intel/avs/boards/probe.c +++ b/sound/soc/intel/avs/boards/probe.c @@ -36,7 +36,8 @@ static int avs_probe_mb_probe(struct platform_device *pdev) if (!card) return -ENOMEM; - card->name = "avs_probe_mb"; + card->driver_name = "avs_probe_mb"; + card->long_name = card->name = "AVS PROBE"; card->dev = dev; card->owner = THIS_MODULE; card->dai_link = probe_mb_dai_links; @@ -47,7 +48,7 @@ static int avs_probe_mb_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_probe_mb_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c index 29977aee2153..ec5382925157 100644 --- a/sound/soc/intel/avs/boards/rt274.c +++ b/sound/soc/intel/avs/boards/rt274.c @@ -210,6 +210,7 @@ static int avs_rt274_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; @@ -218,6 +219,7 @@ static int avs_rt274_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -234,7 +236,12 @@ static int avs_rt274_probe(struct platform_device *pdev) if (!jack || !card) return -ENOMEM; - card->name = "avs_rt274"; + if (pdata->obsolete_card_names) { + card->name = "avs_rt274"; + } else { + card->driver_name = "avs_rt274"; + card->long_name = card->name = "AVS I2S ALC274"; + } card->dev = dev; card->owner = THIS_MODULE; card->suspend_pre = avs_card_suspend_pre; @@ -254,7 +261,7 @@ static int avs_rt274_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_rt274_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c index 6a27c6a9f394..2566e971ce1c 100644 --- a/sound/soc/intel/avs/boards/rt286.c +++ b/sound/soc/intel/avs/boards/rt286.c @@ -179,6 +179,7 @@ static int avs_rt286_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; @@ -187,6 +188,7 @@ static int avs_rt286_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -204,7 +206,12 @@ static int avs_rt286_probe(struct platform_device *pdev) if (!jack || !card) return -ENOMEM; - card->name = "avs_rt286"; + if (pdata->obsolete_card_names) { + card->name = "avs_rt286"; + } else { + card->driver_name = "avs_rt286"; + card->long_name = card->name = "AVS I2S ALC286"; + } card->dev = dev; card->owner = THIS_MODULE; card->suspend_pre = avs_card_suspend_pre; @@ -224,7 +231,7 @@ static int avs_rt286_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_rt286_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c index a7a463d6f852..7be34c8ad167 100644 --- a/sound/soc/intel/avs/boards/rt298.c +++ b/sound/soc/intel/avs/boards/rt298.c @@ -199,6 +199,7 @@ static int avs_rt298_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; @@ -207,6 +208,7 @@ static int avs_rt298_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -223,7 +225,12 @@ static int avs_rt298_probe(struct platform_device *pdev) if (!jack || !card) return -ENOMEM; - card->name = "avs_rt298"; + if (pdata->obsolete_card_names) { + card->name = "avs_rt298"; + } else { + card->driver_name = "avs_rt298"; + card->long_name = card->name = "AVS I2S ALC298"; + } card->dev = dev; card->owner = THIS_MODULE; card->suspend_pre = avs_card_suspend_pre; @@ -243,7 +250,7 @@ static int avs_rt298_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_rt298_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/rt5514.c b/sound/soc/intel/avs/boards/rt5514.c index d1c3e29a28ff..45f091f2ce22 100644 --- a/sound/soc/intel/avs/boards/rt5514.c +++ b/sound/soc/intel/avs/boards/rt5514.c @@ -133,6 +133,7 @@ static int avs_rt5514_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; @@ -140,6 +141,7 @@ static int avs_rt5514_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -155,7 +157,12 @@ static int avs_rt5514_probe(struct platform_device *pdev) if (!card) return -ENOMEM; - card->name = "avs_rt5514"; + if (pdata->obsolete_card_names) { + card->name = "avs_rt5514"; + } else { + card->driver_name = "avs_rt5514"; + card->long_name = card->name = "AVS I2S ALC5514"; + } card->dev = dev; card->owner = THIS_MODULE; card->dai_link = dai_link; @@ -170,7 +177,7 @@ static int avs_rt5514_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_rt5514_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/rt5663.c b/sound/soc/intel/avs/boards/rt5663.c index e3310b3268ba..51648801710a 100644 --- a/sound/soc/intel/avs/boards/rt5663.c +++ b/sound/soc/intel/avs/boards/rt5663.c @@ -198,6 +198,7 @@ static int avs_rt5663_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct rt5663_private *priv; struct device *dev = &pdev->dev; @@ -206,6 +207,7 @@ static int avs_rt5663_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -222,7 +224,12 @@ static int avs_rt5663_probe(struct platform_device *pdev) if (!priv || !card) return -ENOMEM; - card->name = "avs_rt5663"; + if (pdata->obsolete_card_names) { + card->name = "avs_rt5663"; + } else { + card->driver_name = "avs_rt5663"; + card->long_name = card->name = "AVS I2S ALC5663"; + } card->dev = dev; card->owner = THIS_MODULE; card->suspend_pre = avs_card_suspend_pre; @@ -242,7 +249,7 @@ static int avs_rt5663_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_rt5663_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c index 339df0b944c1..9677b9ebeff1 100644 --- a/sound/soc/intel/avs/boards/rt5682.c +++ b/sound/soc/intel/avs/boards/rt5682.c @@ -268,6 +268,7 @@ static int avs_rt5682_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct snd_soc_jack *jack; struct device *dev = &pdev->dev; @@ -282,6 +283,7 @@ static int avs_rt5682_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -298,7 +300,12 @@ static int avs_rt5682_probe(struct platform_device *pdev) if (!jack || !card) return -ENOMEM; - card->name = "avs_rt5682"; + if (pdata->obsolete_card_names) { + card->name = "avs_rt5682"; + } else { + card->driver_name = "avs_rt5682"; + card->long_name = card->name = "AVS I2S ALC5682"; + } card->dev = dev; card->owner = THIS_MODULE; card->suspend_pre = avs_card_suspend_pre; @@ -318,7 +325,7 @@ static int avs_rt5682_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_rt5682_driver_ids[] = { diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c index 7667790d5273..3786eef8c494 100644 --- a/sound/soc/intel/avs/boards/ssm4567.c +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -132,6 +132,7 @@ static int avs_ssm4567_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; @@ -139,6 +140,7 @@ static int avs_ssm4567_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; + pdata = mach->pdata; ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); if (ret) @@ -154,7 +156,12 @@ static int avs_ssm4567_probe(struct platform_device *pdev) if (!card) return -ENOMEM; - card->name = "avs_ssm4567"; + if (pdata->obsolete_card_names) { + card->name = "avs_ssm4567"; + } else { + card->driver_name = "avs_ssm4567"; + card->long_name = card->name = "AVS I2S SSM4567"; + } card->dev = dev; card->owner = THIS_MODULE; card->dai_link = dai_link; @@ -173,7 +180,7 @@ static int avs_ssm4567_probe(struct platform_device *pdev) if (ret) return ret; - return devm_snd_soc_register_card(dev, card); + return devm_snd_soc_register_deferrable_card(dev, card); } static const struct platform_device_id avs_ssm4567_driver_ids[] = { diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index 6ef49f10e19f..d45e9279df27 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -454,7 +454,7 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) return ret; } - ret = pci_request_regions(pci, "AVS HDAudio"); + ret = pcim_request_all_regions(pci, "AVS HDAudio"); if (ret < 0) return ret; @@ -462,8 +462,7 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) bus->remap_addr = pci_ioremap_bar(pci, 0); if (!bus->remap_addr) { dev_err(bus->dev, "ioremap error\n"); - ret = -ENXIO; - goto err_remap_bar0; + return -ENXIO; } adev->dsp_ba = pci_ioremap_bar(pci, 4); @@ -520,8 +519,6 @@ err_init_streams: iounmap(adev->dsp_ba); err_remap_bar4: iounmap(bus->remap_addr); -err_remap_bar0: - pci_release_regions(pci); return ret; } @@ -592,7 +589,6 @@ static void avs_pci_remove(struct pci_dev *pci) pci_free_irq_vectors(pci); iounmap(bus->remap_addr); iounmap(adev->dsp_ba); - pci_release_regions(pci); /* Firmware is not needed anymore */ avs_release_firmwares(adev); @@ -763,6 +759,11 @@ static const struct avs_sram_spec apl_sram_spec = { .window_size = APL_ADSP_SRAM_WINDOW_SIZE, }; +static const struct avs_sram_spec mtl_sram_spec = { + .base_offset = MTL_ADSP_SRAM_BASE_OFFSET, + .window_size = MTL_ADSP_SRAM_WINDOW_SIZE, +}; + static const struct avs_hipc_spec skl_hipc_spec = { .req_offset = SKL_ADSP_REG_HIPCI, .req_ext_offset = SKL_ADSP_REG_HIPCIE, @@ -799,6 +800,18 @@ static const struct avs_hipc_spec cnl_hipc_spec = { .sts_offset = APL_ADSP_SRAM_BASE_OFFSET, }; +static const struct avs_hipc_spec lnl_hipc_spec = { + .req_offset = MTL_REG_HfIPCxIDR, + .req_ext_offset = MTL_REG_HfIPCxIDD, + .req_busy_mask = MTL_HfIPCxIDR_BUSY, + .ack_offset = MTL_REG_HfIPCxIDA, + .ack_done_mask = MTL_HfIPCxIDA_DONE, + .rsp_offset = MTL_REG_HfIPCxTDR, + .rsp_busy_mask = MTL_HfIPCxTDR_BUSY, + .ctl_offset = MTL_REG_HfIPCxCTL, + .sts_offset = LNL_REG_HfDFR(0), +}; + static const struct avs_spec skl_desc = { .name = "skl", .min_fw_version = { 9, 21, 0, 4732 }, @@ -866,6 +879,16 @@ AVS_TGL_BASED_SPEC(ehl, 30); AVS_TGL_BASED_SPEC(adl, 35); AVS_TGL_BASED_SPEC(adl_n, 35); +static const struct avs_spec fcl_desc = { + .name = "fcl", + .min_fw_version = { 0 }, + .dsp_ops = &avs_ptl_dsp_ops, + .core_init_mask = 1, + .attributes = AVS_PLATATTR_IMR | AVS_PLATATTR_ACE | AVS_PLATATTR_ALTHDA, + .sram = &mtl_sram_spec, + .hipc = &lnl_hipc_spec, +}; + static const struct pci_device_id avs_ids[] = { { PCI_DEVICE_DATA(INTEL, HDA_SKL_LP, &skl_desc) }, { PCI_DEVICE_DATA(INTEL, HDA_SKL, &skl_desc) }, @@ -901,6 +924,7 @@ static const struct pci_device_id avs_ids[] = { { PCI_DEVICE_DATA(INTEL, HDA_RPL_P_1, &adl_desc) }, { PCI_DEVICE_DATA(INTEL, HDA_RPL_M, &adl_desc) }, { PCI_DEVICE_DATA(INTEL, HDA_RPL_PX, &adl_desc) }, + { PCI_DEVICE_DATA(INTEL, HDA_FCL, &fcl_desc) }, { 0 } }; MODULE_DEVICE_TABLE(pci, avs_ids); @@ -932,3 +956,4 @@ MODULE_FIRMWARE("intel/avs/tgl/dsp_basefw.bin"); MODULE_FIRMWARE("intel/avs/ehl/dsp_basefw.bin"); MODULE_FIRMWARE("intel/avs/adl/dsp_basefw.bin"); MODULE_FIRMWARE("intel/avs/adl_n/dsp_basefw.bin"); +MODULE_FIRMWARE("intel/fcl/dsp_basefw.bin"); diff --git a/sound/soc/intel/avs/debugfs.c b/sound/soc/intel/avs/debugfs.c index 0e826ca20619..c625cf879f17 100644 --- a/sound/soc/intel/avs/debugfs.c +++ b/sound/soc/intel/avs/debugfs.c @@ -144,7 +144,7 @@ static ssize_t probe_points_write(struct file *file, const char __user *from, si int ret; ret = parse_int_array_user(from, count, (int **)&array); - if (ret < 0) + if (ret) return ret; num_elems = *array; @@ -181,7 +181,7 @@ static ssize_t probe_points_disconnect_write(struct file *file, const char __use int ret; ret = parse_int_array_user(from, count, (int **)&array); - if (ret < 0) + if (ret) return ret; num_elems = *array; @@ -369,7 +369,7 @@ static ssize_t trace_control_write(struct file *file, const char __user *from, s int ret; ret = parse_int_array_user(from, count, (int **)&array); - if (ret < 0) + if (ret) return ret; num_elems = *array; diff --git a/sound/soc/intel/avs/dsp.c b/sound/soc/intel/avs/dsp.c index b9de691e9b9b..464bd6859182 100644 --- a/sound/soc/intel/avs/dsp.c +++ b/sound/soc/intel/avs/dsp.c @@ -12,8 +12,6 @@ #include "registers.h" #include "trace.h" -#define AVS_ADSPCS_INTERVAL_US 500 -#define AVS_ADSPCS_TIMEOUT_US 50000 #define AVS_ADSPCS_DELAY_US 1000 int avs_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power) diff --git a/sound/soc/intel/avs/lnl.c b/sound/soc/intel/avs/lnl.c new file mode 100644 index 000000000000..03208596dfb1 --- /dev/null +++ b/sound/soc/intel/avs/lnl.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright(c) 2021-2025 Intel Corporation + * + * Authors: Cezary Rojewski <cezary.rojewski@intel.com> + * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> + */ + +#include <sound/hdaudio_ext.h> +#include "avs.h" +#include "registers.h" + +int avs_lnl_core_stall(struct avs_dev *adev, u32 core_mask, bool stall) +{ + struct hdac_bus *bus = &adev->base.core; + struct hdac_ext_link *hlink; + int ret; + + ret = avs_mtl_core_stall(adev, core_mask, stall); + + /* On unstall, route interrupts from the links to the DSP firmware. */ + if (!ret && !stall) + list_for_each_entry(hlink, &bus->hlink_list, list) + snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, AZX_ML_LCTL_OFLEN, + AZX_ML_LCTL_OFLEN); + return ret; +} diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c index 138e4e9de5e3..353e343b1d28 100644 --- a/sound/soc/intel/avs/loader.c +++ b/sound/soc/intel/avs/loader.c @@ -9,6 +9,7 @@ #include <linux/firmware.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/string.h> #include <sound/hdaudio.h> #include <sound/hdaudio_ext.h> #include "avs.h" diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 2f243802ccc2..55c04b0142ae 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -102,6 +102,8 @@ struct avs_tlv { } __packed; static_assert(sizeof(struct avs_tlv) == 8); +#define avs_tlv_size(tlv) struct_size(tlv, value, (tlv)->length / 4) + enum avs_module_msg_type { AVS_MOD_INIT_INSTANCE = 0, AVS_MOD_LARGE_CONFIG_GET = 3, @@ -697,8 +699,9 @@ enum avs_sample_type { AVS_SAMPLE_TYPE_FLOAT = 4, }; -#define AVS_CHANNELS_MAX 8 +#define AVS_COEFF_CHANNELS_MAX 8 #define AVS_ALL_CHANNELS_MASK UINT_MAX +#define AVS_CHANNELS_MAX 16 struct avs_audio_format { u32 sampling_freq; @@ -786,6 +789,33 @@ union avs_gtw_attributes { } __packed; static_assert(sizeof(union avs_gtw_attributes) == 4); +#define AVS_GTW_DMA_CONFIG_ID 0x1000 +#define AVS_DMA_METHOD_HDA 1 + +struct avs_dma_device_stream_channel_map { + u32 device_address; + u32 channel_map; +} __packed; +static_assert(sizeof(struct avs_dma_device_stream_channel_map) == 8); + +struct avs_dma_stream_channel_map { + u32 device_count; + struct avs_dma_device_stream_channel_map map[16]; +} __packed; +static_assert(sizeof(struct avs_dma_stream_channel_map) == 132); + +struct avs_dma_cfg { + u8 dma_method; + u8 pre_allocated; + u16 rsvd; + u32 dma_channel_id; + u32 stream_id; + struct avs_dma_stream_channel_map map; + u32 config_size; + u8 config[] __counted_by(config_size); +} __packed; +static_assert(sizeof(struct avs_dma_cfg) == 148); + struct avs_copier_gtw_cfg { union avs_connector_node_id node_id; u32 dma_buffer_size; @@ -846,7 +876,7 @@ struct avs_updown_mixer_cfg { struct avs_modcfg_base base; u32 out_channel_config; u32 coefficients_select; - s32 coefficients[AVS_CHANNELS_MAX]; + s32 coefficients[AVS_COEFF_CHANNELS_MAX]; u32 channel_map; } __packed; static_assert(sizeof(struct avs_updown_mixer_cfg) == 84); diff --git a/sound/soc/intel/avs/mtl.c b/sound/soc/intel/avs/mtl.c new file mode 100644 index 000000000000..e7b7915b2a82 --- /dev/null +++ b/sound/soc/intel/avs/mtl.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright(c) 2021-2025 Intel Corporation + * + * Authors: Cezary Rojewski <cezary.rojewski@intel.com> + * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> + */ + +#include <sound/hdaudio_ext.h> +#include "avs.h" +#include "registers.h" +#include "trace.h" + +#define MTL_HfDSSGBL_BASE 0x1000 +#define MTL_REG_HfDSSCS (MTL_HfDSSGBL_BASE + 0x0) +#define MTL_HfDSSCS_SPA BIT(16) +#define MTL_HfDSSCS_CPA BIT(24) + +#define MTL_DSPCS_BASE 0x178D00 +#define MTL_REG_DSPCCTL (MTL_DSPCS_BASE + 0x4) +#define MTL_DSPCCTL_SPA BIT(0) +#define MTL_DSPCCTL_CPA BIT(8) +#define MTL_DSPCCTL_OSEL GENMASK(25, 24) +#define MTL_DSPCCTL_OSEL_HOST BIT(25) + +#define MTL_HfINT_BASE 0x1100 +#define MTL_REG_HfINTIPPTR (MTL_HfINT_BASE + 0x8) +#define MTL_REG_HfHIPCIE (MTL_HfINT_BASE + 0x40) +#define MTL_HfINTIPPTR_PTR GENMASK(20, 0) +#define MTL_HfHIPCIE_IE BIT(0) + +#define MTL_DWICTL_INTENL_IE BIT(0) +#define MTL_DWICTL_FINALSTATUSL_IPC BIT(0) /* same as ADSPIS_IPC */ + +static int avs_mtl_core_power_on(struct avs_dev *adev) +{ + u32 reg; + int ret; + + /* Power up DSP domain. */ + snd_hdac_adsp_updatel(adev, MTL_REG_HfDSSCS, MTL_HfDSSCS_SPA, MTL_HfDSSCS_SPA); + trace_avs_dsp_core_op(1, AVS_MAIN_CORE_MASK, "power dsp", true); + + ret = snd_hdac_adsp_readl_poll(adev, MTL_REG_HfDSSCS, reg, + (reg & MTL_HfDSSCS_CPA) == MTL_HfDSSCS_CPA, + AVS_ADSPCS_INTERVAL_US, AVS_ADSPCS_TIMEOUT_US); + if (ret) { + dev_err(adev->dev, "power on domain dsp failed: %d\n", ret); + return ret; + } + + /* Prevent power gating of DSP domain. */ + snd_hdac_adsp_updatel(adev, MTL_REG_HfPWRCTL, MTL_HfPWRCTL_WPDSPHPxPG, + MTL_HfPWRCTL_WPDSPHPxPG); + trace_avs_dsp_core_op(1, AVS_MAIN_CORE_MASK, "prevent dsp PG", true); + + ret = snd_hdac_adsp_readl_poll(adev, MTL_REG_HfPWRSTS, reg, + (reg & MTL_HfPWRSTS_DSPHPxPGS) == MTL_HfPWRSTS_DSPHPxPGS, + AVS_ADSPCS_INTERVAL_US, AVS_ADSPCS_TIMEOUT_US); + + /* Set ownership to HOST. */ + snd_hdac_adsp_updatel(adev, MTL_REG_DSPCCTL, MTL_DSPCCTL_OSEL, MTL_DSPCCTL_OSEL_HOST); + return ret; +} + +static int avs_mtl_core_power_off(struct avs_dev *adev) +{ + u32 reg; + + /* Allow power gating of DSP domain. No STS polling as HOST is only one of its users. */ + snd_hdac_adsp_updatel(adev, MTL_REG_HfPWRCTL, MTL_HfPWRCTL_WPDSPHPxPG, 0); + trace_avs_dsp_core_op(0, AVS_MAIN_CORE_MASK, "allow dsp pg", false); + + /* Power down DSP domain. */ + snd_hdac_adsp_updatel(adev, MTL_REG_HfDSSCS, MTL_HfDSSCS_SPA, 0); + trace_avs_dsp_core_op(0, AVS_MAIN_CORE_MASK, "power dsp", false); + + return snd_hdac_adsp_readl_poll(adev, MTL_REG_HfDSSCS, reg, + (reg & MTL_HfDSSCS_CPA) == 0, + AVS_ADSPCS_INTERVAL_US, AVS_ADSPCS_TIMEOUT_US); +} + +int avs_mtl_core_power(struct avs_dev *adev, u32 core_mask, bool power) +{ + core_mask &= AVS_MAIN_CORE_MASK; + if (!core_mask) + return 0; + + if (power) + return avs_mtl_core_power_on(adev); + return avs_mtl_core_power_off(adev); +} + +int avs_mtl_core_reset(struct avs_dev *adev, u32 core_mask, bool power) +{ + /* No logical equivalent on ACE 1.x. */ + return 0; +} + +int avs_mtl_core_stall(struct avs_dev *adev, u32 core_mask, bool stall) +{ + u32 value, reg; + int ret; + + core_mask &= AVS_MAIN_CORE_MASK; + if (!core_mask) + return 0; + + value = snd_hdac_adsp_readl(adev, MTL_REG_DSPCCTL); + trace_avs_dsp_core_op(value, core_mask, "stall", stall); + if (value == UINT_MAX) + return 0; + + value = stall ? 0 : MTL_DSPCCTL_SPA; + snd_hdac_adsp_updatel(adev, MTL_REG_DSPCCTL, MTL_DSPCCTL_SPA, value); + + value = stall ? 0 : MTL_DSPCCTL_CPA; + ret = snd_hdac_adsp_readl_poll(adev, MTL_REG_DSPCCTL, + reg, (reg & MTL_DSPCCTL_CPA) == value, + AVS_ADSPCS_INTERVAL_US, AVS_ADSPCS_TIMEOUT_US); + if (ret) + dev_err(adev->dev, "core_mask %d %sstall failed: %d\n", + core_mask, stall ? "" : "un", ret); + return ret; +} + +static void avs_mtl_ipc_interrupt(struct avs_dev *adev) +{ + const struct avs_spec *spec = adev->spec; + u32 hipc_ack, hipc_rsp; + + snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, 0); + + hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset); + hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset); + + /* DSP acked host's request. */ + if (hipc_ack & spec->hipc->ack_done_mask) { + complete(&adev->ipc->done_completion); + + /* Tell DSP it has our attention. */ + snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset, spec->hipc->ack_done_mask, + spec->hipc->ack_done_mask); + } + + /* DSP sent new response to process. */ + if (hipc_rsp & spec->hipc->rsp_busy_mask) { + union avs_reply_msg msg; + + msg.primary = snd_hdac_adsp_readl(adev, MTL_REG_HfIPCxTDR); + msg.ext.val = snd_hdac_adsp_readl(adev, MTL_REG_HfIPCxTDD); + + avs_dsp_process_response(adev, msg.val); + + /* Tell DSP we accepted its message. */ + snd_hdac_adsp_updatel(adev, MTL_REG_HfIPCxTDR, + MTL_HfIPCxTDR_BUSY, MTL_HfIPCxTDR_BUSY); + /* Ack this response. */ + snd_hdac_adsp_updatel(adev, MTL_REG_HfIPCxTDA, MTL_HfIPCxTDA_BUSY, 0); + } + + snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY); +} + +irqreturn_t avs_mtl_dsp_interrupt(struct avs_dev *adev) +{ + u32 adspis = snd_hdac_adsp_readl(adev, MTL_DWICTL_REG_FINALSTATUSL); + irqreturn_t ret = IRQ_NONE; + + if (adspis == UINT_MAX) + return ret; + + if (adspis & MTL_DWICTL_FINALSTATUSL_IPC) { + avs_mtl_ipc_interrupt(adev); + ret = IRQ_HANDLED; + } + + return ret; +} + +void avs_mtl_interrupt_control(struct avs_dev *adev, bool enable) +{ + if (enable) { + snd_hdac_adsp_updatel(adev, MTL_DWICTL_REG_INTENL, MTL_DWICTL_INTENL_IE, + MTL_DWICTL_INTENL_IE); + snd_hdac_adsp_updatew(adev, MTL_REG_HfHIPCIE, MTL_HfHIPCIE_IE, MTL_HfHIPCIE_IE); + snd_hdac_adsp_updatel(adev, MTL_REG_HfIPCxCTL, AVS_ADSP_HIPCCTL_DONE, + AVS_ADSP_HIPCCTL_DONE); + snd_hdac_adsp_updatel(adev, MTL_REG_HfIPCxCTL, AVS_ADSP_HIPCCTL_BUSY, + AVS_ADSP_HIPCCTL_BUSY); + } else { + snd_hdac_adsp_updatel(adev, MTL_REG_HfIPCxCTL, AVS_ADSP_HIPCCTL_BUSY, 0); + snd_hdac_adsp_updatel(adev, MTL_REG_HfIPCxCTL, AVS_ADSP_HIPCCTL_DONE, 0); + snd_hdac_adsp_updatew(adev, MTL_REG_HfHIPCIE, MTL_HfHIPCIE_IE, 0); + snd_hdac_adsp_updatel(adev, MTL_DWICTL_REG_INTENL, MTL_DWICTL_INTENL_IE, 0); + } +} diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 43b3d9953910..e8e6b1c7fc90 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -284,8 +284,51 @@ avs_nhlt_config_or_default(struct avs_dev *adev, struct avs_tplg_module *t) return &fmtcfg->config; } +static int avs_append_dma_cfg(struct avs_dev *adev, struct avs_copier_gtw_cfg *gtw, + struct avs_tplg_module *t, u32 dma_id, size_t *cfg_size) +{ + u32 dma_type = t->cfg_ext->copier.dma_type; + struct avs_dma_cfg *dma; + struct avs_tlv *tlv; + size_t tlv_size; + + if (!avs_platattr_test(adev, ALTHDA)) + return 0; + + switch (dma_type) { + case AVS_DMA_HDA_HOST_OUTPUT: + case AVS_DMA_HDA_HOST_INPUT: + case AVS_DMA_HDA_LINK_OUTPUT: + case AVS_DMA_HDA_LINK_INPUT: + return 0; + default: + break; + } + + tlv_size = sizeof(*tlv) + sizeof(*dma); + if (*cfg_size + tlv_size > AVS_MAILBOX_SIZE) + return -E2BIG; + + /* DMA config is a TLV tailing the existing payload. */ + tlv = (struct avs_tlv *)>w->config.blob[gtw->config_length]; + tlv->type = AVS_GTW_DMA_CONFIG_ID; + tlv->length = sizeof(*dma); + + dma = (struct avs_dma_cfg *)tlv->value; + memset(dma, 0, sizeof(*dma)); + dma->dma_method = AVS_DMA_METHOD_HDA; + dma->pre_allocated = true; + dma->dma_channel_id = dma_id; + dma->stream_id = dma_id + 1; + + gtw->config_length += tlv_size / sizeof(u32); + *cfg_size += tlv_size; + + return 0; +} + static int avs_fill_gtw_config(struct avs_dev *adev, struct avs_copier_gtw_cfg *gtw, - struct avs_tplg_module *t, size_t *cfg_size) + struct avs_tplg_module *t, u32 dma_id, size_t *cfg_size) { struct acpi_nhlt_config *blob; size_t gtw_size; @@ -302,7 +345,7 @@ static int avs_fill_gtw_config(struct avs_dev *adev, struct avs_copier_gtw_cfg * memcpy(gtw->config.blob, blob->capabilities, blob->capabilities_size); *cfg_size += gtw_size; - return 0; + return avs_append_dma_cfg(adev, gtw, t, dma_id, cfg_size); } static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) @@ -319,7 +362,7 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) dma_id = mod->owner->owner->dma_id; cfg_size = offsetof(struct avs_copier_cfg, gtw_cfg.config); - ret = avs_fill_gtw_config(adev, &cfg->gtw_cfg, t, &cfg_size); + ret = avs_fill_gtw_config(adev, &cfg->gtw_cfg, t, dma_id, &cfg_size); if (ret) return ret; @@ -353,7 +396,7 @@ static int avs_whm_create(struct avs_dev *adev, struct avs_path_module *mod) dma_id = mod->owner->owner->dma_id; cfg_size = offsetof(struct avs_whm_cfg, gtw_cfg.config); - ret = avs_fill_gtw_config(adev, &cfg->gtw_cfg, t, &cfg_size); + ret = avs_fill_gtw_config(adev, &cfg->gtw_cfg, t, dma_id, &cfg_size); if (ret) return ret; @@ -526,7 +569,7 @@ static int avs_updown_mix_create(struct avs_dev *adev, struct avs_path_module *m cfg.base.audio_fmt = *t->in_fmt; cfg.out_channel_config = t->cfg_ext->updown_mix.out_channel_config; cfg.coefficients_select = t->cfg_ext->updown_mix.coefficients_select; - for (i = 0; i < AVS_CHANNELS_MAX; i++) + for (i = 0; i < AVS_COEFF_CHANNELS_MAX; i++) cfg.coefficients[i] = t->cfg_ext->updown_mix.coefficients[i]; cfg.channel_map = t->cfg_ext->updown_mix.channel_map; diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 5a2330e4e422..0efe490024b0 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -18,6 +18,7 @@ #include "path.h" #include "pcm.h" #include "topology.h" +#include "utils.h" #include "../../codecs/hda.h" struct avs_dma_data { @@ -548,7 +549,6 @@ static const struct snd_soc_dai_ops avs_dai_hda_be_ops = { .trigger = avs_dai_hda_be_trigger, }; -__maybe_unused static const struct snd_soc_dai_ops avs_dai_i2shda_be_ops = { .startup = avs_dai_i2shda_be_startup, .shutdown = avs_dai_althda_be_shutdown, @@ -558,7 +558,6 @@ static const struct snd_soc_dai_ops avs_dai_i2shda_be_ops = { .trigger = avs_dai_hda_be_trigger, }; -__maybe_unused static const struct snd_soc_dai_ops avs_dai_dmichda_be_ops = { .startup = avs_dai_dmichda_be_startup, .shutdown = avs_dai_althda_be_shutdown, @@ -1367,7 +1366,7 @@ static int avs_component_construct(struct snd_soc_component *component, return 0; } -static const struct snd_soc_component_driver avs_component_driver = { +static struct snd_soc_component_driver avs_component_driver = { .name = "avs-pcm", .probe = avs_component_probe, .remove = avs_component_remove, @@ -1382,7 +1381,7 @@ static const struct snd_soc_component_driver avs_component_driver = { }; int avs_soc_component_register(struct device *dev, const char *name, - const struct snd_soc_component_driver *drv, + struct snd_soc_component_driver *drv, struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais) { struct avs_soc_component *acomp; @@ -1400,13 +1399,14 @@ int avs_soc_component_register(struct device *dev, const char *name, acomp->base.name = name; INIT_LIST_HEAD(&acomp->node); + drv->use_dai_pcm_id = !obsolete_card_names; + return snd_soc_add_component(&acomp->base, cpu_dais, num_cpu_dais); } static struct snd_soc_dai_driver dmic_cpu_dais[] = { { .name = "DMIC Pin", - .ops = &avs_dai_nonhda_be_ops, .capture = { .stream_name = "DMIC Rx", .channels_min = 1, @@ -1417,7 +1417,6 @@ static struct snd_soc_dai_driver dmic_cpu_dais[] = { }, { .name = "DMIC WoV Pin", - .ops = &avs_dai_nonhda_be_ops, .capture = { .stream_name = "DMIC WoV Rx", .channels_min = 1, @@ -1430,15 +1429,23 @@ static struct snd_soc_dai_driver dmic_cpu_dais[] = { int avs_dmic_platform_register(struct avs_dev *adev, const char *name) { + const struct snd_soc_dai_ops *ops; + + if (avs_platattr_test(adev, ALTHDA)) + ops = &avs_dai_dmichda_be_ops; + else + ops = &avs_dai_nonhda_be_ops; + + dmic_cpu_dais[0].ops = ops; + dmic_cpu_dais[1].ops = ops; return avs_soc_component_register(adev->dev, name, &avs_component_driver, dmic_cpu_dais, ARRAY_SIZE(dmic_cpu_dais)); } static const struct snd_soc_dai_driver i2s_dai_template = { - .ops = &avs_dai_nonhda_be_ops, .playback = { .channels_min = 1, - .channels_max = 8, + .channels_max = AVS_CHANNELS_MAX, .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_24000 | @@ -1451,7 +1458,7 @@ static const struct snd_soc_dai_driver i2s_dai_template = { }, .capture = { .channels_min = 1, - .channels_max = 8, + .channels_max = AVS_CHANNELS_MAX, .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_24000 | @@ -1468,10 +1475,15 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l unsigned long *tdms) { struct snd_soc_dai_driver *cpus, *dai; + const struct snd_soc_dai_ops *ops; size_t ssp_count, cpu_count; int i, j; ssp_count = adev->hw_cfg.i2s_caps.ctrl_count; + if (avs_platattr_test(adev, ALTHDA)) + ops = &avs_dai_i2shda_be_ops; + else + ops = &avs_dai_nonhda_be_ops; cpu_count = 0; for_each_set_bit(i, &port_mask, ssp_count) @@ -1499,6 +1511,7 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name) return -ENOMEM; + dai->ops = ops; dai++; } } @@ -1507,7 +1520,7 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l goto plat_register; for_each_set_bit(i, &port_mask, ssp_count) { - for_each_set_bit(j, &tdms[i], ssp_count) { + for_each_set_bit(j, &tdms[i], AVS_CHANNELS_MAX) { memcpy(dai, &i2s_dai_template, sizeof(*dai)); dai->name = @@ -1519,6 +1532,7 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name) return -ENOMEM; + dai->ops = ops; dai++; } } @@ -1532,7 +1546,7 @@ static const struct snd_soc_dai_driver hda_cpu_dai = { .ops = &avs_dai_hda_be_ops, .playback = { .channels_min = 1, - .channels_max = 8, + .channels_max = AVS_CHANNELS_MAX, .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, @@ -1542,7 +1556,7 @@ static const struct snd_soc_dai_driver hda_cpu_dai = { }, .capture = { .channels_min = 1, - .channels_max = 8, + .channels_max = AVS_CHANNELS_MAX, .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, @@ -1556,11 +1570,13 @@ static void avs_component_hda_unregister_dais(struct snd_soc_component *componen { struct snd_soc_acpi_mach *mach; struct snd_soc_dai *dai, *save; + struct avs_mach_pdata *pdata; struct hda_codec *codec; char name[32]; mach = dev_get_platdata(component->card->dev); - codec = mach->pdata; + pdata = mach->pdata; + codec = pdata->codec; snprintf(name, sizeof(name), "%s-cpu", dev_name(&codec->core.dev)); for_each_component_dais_safe(component, dai, save) { @@ -1581,6 +1597,7 @@ static int avs_component_hda_probe(struct snd_soc_component *component) struct snd_soc_dapm_context *dapm; struct snd_soc_dai_driver *dais; struct snd_soc_acpi_mach *mach; + struct avs_mach_pdata *pdata; struct hda_codec *codec; struct hda_pcm *pcm; const char *cname; @@ -1590,7 +1607,8 @@ static int avs_component_hda_probe(struct snd_soc_component *component) if (!mach) return -EINVAL; - codec = mach->pdata; + pdata = mach->pdata; + codec = pdata->codec; if (list_empty(&codec->pcm_list_head)) return -EINVAL; list_for_each_entry(pcm, &codec->pcm_list_head, list) @@ -1724,7 +1742,7 @@ static int avs_component_hda_open(struct snd_soc_component *component, return 0; } -static const struct snd_soc_component_driver avs_hda_component_driver = { +static struct snd_soc_component_driver avs_hda_component_driver = { .name = "avs-hda-pcm", .probe = avs_component_hda_probe, .remove = avs_component_hda_remove, diff --git a/sound/soc/intel/avs/probes.c b/sound/soc/intel/avs/probes.c index f0b010956303..a42736b9aa55 100644 --- a/sound/soc/intel/avs/probes.c +++ b/sound/soc/intel/avs/probes.c @@ -284,7 +284,7 @@ static struct snd_soc_dai_driver probe_cpu_dais[] = { }, }; -static const struct snd_soc_component_driver avs_probe_component_driver = { +static struct snd_soc_component_driver avs_probe_component_driver = { .name = "avs-probe-compr", .compress_ops = &avs_probe_compress_ops, .module_get_upon_open = 1, /* increment refcount when a stream is opened */ diff --git a/sound/soc/intel/avs/ptl.c b/sound/soc/intel/avs/ptl.c new file mode 100644 index 000000000000..2be4b545c91d --- /dev/null +++ b/sound/soc/intel/avs/ptl.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright(c) 2024-2025 Intel Corporation + * + * Authors: Cezary Rojewski <cezary.rojewski@intel.com> + * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> + */ + +#include <sound/hdaudio_ext.h> +#include "avs.h" +#include "registers.h" +#include "trace.h" + +#define MTL_HfDSSGBL_BASE 0x1000 +#define MTL_REG_HfDSSCS (MTL_HfDSSGBL_BASE + 0x0) +#define MTL_HfDSSCS_SPA BIT(16) +#define MTL_HfDSSCS_CPA BIT(24) + +#define MTL_DSPCS_BASE 0x178D00 +#define MTL_REG_DSPCCTL (MTL_DSPCS_BASE + 0x4) +#define MTL_DSPCCTL_OSEL GENMASK(25, 24) +#define MTL_DSPCCTL_OSEL_HOST BIT(25) + +static int avs_ptl_core_power_on(struct avs_dev *adev) +{ + u32 reg; + int ret; + + /* Power up DSP domain. */ + snd_hdac_adsp_updatel(adev, MTL_REG_HfDSSCS, MTL_HfDSSCS_SPA, MTL_HfDSSCS_SPA); + trace_avs_dsp_core_op(1, AVS_MAIN_CORE_MASK, "power dsp", true); + + ret = snd_hdac_adsp_readl_poll(adev, MTL_REG_HfDSSCS, reg, + (reg & MTL_HfDSSCS_CPA) == MTL_HfDSSCS_CPA, + AVS_ADSPCS_INTERVAL_US, AVS_ADSPCS_TIMEOUT_US); + if (ret) { + dev_err(adev->dev, "power on domain dsp failed: %d\n", ret); + return ret; + } + + /* Prevent power gating of DSP domain. */ + snd_hdac_adsp_updatel(adev, MTL_REG_HfPWRCTL2, MTL_HfPWRCTL2_WPDSPHPxPG, + MTL_HfPWRCTL2_WPDSPHPxPG); + trace_avs_dsp_core_op(1, AVS_MAIN_CORE_MASK, "prevent dsp PG", true); + + ret = snd_hdac_adsp_readl_poll(adev, MTL_REG_HfPWRSTS2, reg, + (reg & MTL_HfPWRSTS2_DSPHPxPGS) == MTL_HfPWRSTS2_DSPHPxPGS, + AVS_ADSPCS_INTERVAL_US, AVS_ADSPCS_TIMEOUT_US); + + /* Set ownership to HOST. */ + snd_hdac_adsp_updatel(adev, MTL_REG_DSPCCTL, MTL_DSPCCTL_OSEL, MTL_DSPCCTL_OSEL_HOST); + return ret; +} + +static int avs_ptl_core_power_off(struct avs_dev *adev) +{ + u32 reg; + + /* Allow power gating of DSP domain. No STS polling as HOST is only one of its users. */ + snd_hdac_adsp_updatel(adev, MTL_REG_HfPWRCTL2, MTL_HfPWRCTL2_WPDSPHPxPG, 0); + trace_avs_dsp_core_op(0, AVS_MAIN_CORE_MASK, "allow dsp pg", false); + + /* Power down DSP domain. */ + snd_hdac_adsp_updatel(adev, MTL_REG_HfDSSCS, MTL_HfDSSCS_SPA, 0); + trace_avs_dsp_core_op(0, AVS_MAIN_CORE_MASK, "power dsp", false); + + return snd_hdac_adsp_readl_poll(adev, MTL_REG_HfDSSCS, reg, + (reg & MTL_HfDSSCS_CPA) == 0, + AVS_ADSPCS_INTERVAL_US, AVS_ADSPCS_TIMEOUT_US); +} + +static int avs_ptl_core_power(struct avs_dev *adev, u32 core_mask, bool power) +{ + core_mask &= AVS_MAIN_CORE_MASK; + if (!core_mask) + return 0; + + if (power) + return avs_ptl_core_power_on(adev); + return avs_ptl_core_power_off(adev); +} + +const struct avs_dsp_ops avs_ptl_dsp_ops = { + .power = avs_ptl_core_power, + .reset = avs_mtl_core_reset, + .stall = avs_lnl_core_stall, + .dsp_interrupt = avs_mtl_dsp_interrupt, + .int_control = avs_mtl_interrupt_control, + .load_basefw = avs_hda_load_basefw, + .load_lib = avs_hda_load_library, + .transfer_mods = avs_hda_transfer_modules, + .log_buffer_offset = avs_icl_log_buffer_offset, + .log_buffer_status = avs_apl_log_buffer_status, + .coredump = avs_apl_coredump, + .d0ix_toggle = avs_icl_d0ix_toggle, + .set_d0ix = avs_icl_set_d0ix, + AVS_SET_ENABLE_LOGS_OP(icl) +}; diff --git a/sound/soc/intel/avs/registers.h b/sound/soc/intel/avs/registers.h index 4db0cdf68ffc..97767882ffa1 100644 --- a/sound/soc/intel/avs/registers.h +++ b/sound/soc/intel/avs/registers.h @@ -35,6 +35,8 @@ #define AVS_ADSPCS_CSTALL_MASK(cm) ((cm) << 8) #define AVS_ADSPCS_SPA_MASK(cm) ((cm) << 16) #define AVS_ADSPCS_CPA_MASK(cm) ((cm) << 24) +#define AVS_ADSPCS_INTERVAL_US 500 +#define AVS_ADSPCS_TIMEOUT_US 10000 #define AVS_MAIN_CORE_MASK BIT(0) #define AVS_ADSP_HIPCCTL_BUSY BIT(0) @@ -67,11 +69,47 @@ #define CNL_ADSP_HIPCIDR_BUSY BIT(31) #define CNL_ADSP_HIPCIDA_DONE BIT(31) +/* MTL Intel HOST Inter-Processor Communication Registers */ +#define MTL_HfIPC_BASE 0x73000 +#define MTL_REG_HfIPCxTDR (MTL_HfIPC_BASE + 0x200) +#define MTL_REG_HfIPCxTDA (MTL_HfIPC_BASE + 0x204) +#define MTL_REG_HfIPCxIDR (MTL_HfIPC_BASE + 0x210) +#define MTL_REG_HfIPCxIDA (MTL_HfIPC_BASE + 0x214) +#define MTL_REG_HfIPCxCTL (MTL_HfIPC_BASE + 0x228) +#define MTL_REG_HfIPCxTDD (MTL_HfIPC_BASE + 0x300) +#define MTL_REG_HfIPCxIDD (MTL_HfIPC_BASE + 0x380) + +#define MTL_HfIPCxTDR_BUSY BIT(31) +#define MTL_HfIPCxTDA_BUSY BIT(31) +#define MTL_HfIPCxIDR_BUSY BIT(31) +#define MTL_HfIPCxIDA_DONE BIT(31) + +#define MTL_HfFLV_BASE 0x162000 +#define MTL_REG_HfFLGP(x, y) (MTL_HfFLV_BASE + 0x1200 + (x) * 0x20 + (y) * 0x08) +#define LNL_REG_HfDFR(x) (0x160200 + (x) * 0x8) + +#define MTL_DWICTL_BASE 0x1800 +#define MTL_DWICTL_REG_INTENL (MTL_DWICTL_BASE + 0x0) +#define MTL_DWICTL_REG_FINALSTATUSL (MTL_DWICTL_BASE + 0x30) + +#define MTL_HfPMCCU_BASE 0x1D00 +#define MTL_REG_HfCLKCTL (MTL_HfPMCCU_BASE + 0x10) +#define MTL_REG_HfPWRCTL (MTL_HfPMCCU_BASE + 0x18) +#define MTL_REG_HfPWRSTS (MTL_HfPMCCU_BASE + 0x1C) +#define MTL_REG_HfPWRCTL2 (MTL_HfPMCCU_BASE + 0x20) +#define MTL_REG_HfPWRSTS2 (MTL_HfPMCCU_BASE + 0x24) +#define MTL_HfPWRCTL_WPDSPHPxPG BIT(0) +#define MTL_HfPWRSTS_DSPHPxPGS BIT(0) +#define MTL_HfPWRCTL2_WPDSPHPxPG BIT(0) +#define MTL_HfPWRSTS2_DSPHPxPGS BIT(0) + /* Intel HD Audio SRAM windows base addresses */ #define SKL_ADSP_SRAM_BASE_OFFSET 0x8000 #define SKL_ADSP_SRAM_WINDOW_SIZE 0x2000 #define APL_ADSP_SRAM_BASE_OFFSET 0x80000 #define APL_ADSP_SRAM_WINDOW_SIZE 0x20000 +#define MTL_ADSP_SRAM_BASE_OFFSET 0x180000 +#define MTL_ADSP_SRAM_WINDOW_SIZE 0x8000 /* Constants used when accessing SRAM, space shared with firmware */ #define AVS_FW_REG_BASE(adev) ((adev)->spec->hipc->sts_offset) diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c index 56905f2b9eb2..9dbb3ad0954a 100644 --- a/sound/soc/intel/avs/tgl.c +++ b/sound/soc/intel/avs/tgl.c @@ -47,7 +47,7 @@ static int avs_tgl_config_basefw(struct avs_dev *adev) #ifdef CONFIG_X86 unsigned int ecx; -#include <asm/cpuid.h> +#include <asm/cpuid/api.h> ecx = cpuid_ecx(CPUID_TSC_LEAF); if (ecx) { ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_XTAL_FREQ_HZ, sizeof(ecx), &ecx); diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 3c222c352701..f2e4ad8b8e14 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -1668,8 +1668,8 @@ static int avs_widget_load(struct snd_soc_component *comp, int index, /* See parse_link_formatted_string() for dynamic naming when(s). */ if (avs_mach_singular_tdm(mach, ssp_port)) { - /* size is based on possible %d -> SSP:TDM, where SSP and TDM < 10 + '\0' */ - size_t size = strlen(dw->name) + 2; + /* size is based on possible %d -> SSP:TDM, where SSP and TDM < 16 + '\0' */ + size_t size = strlen(dw->name) + 3; char *buf; tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); diff --git a/sound/soc/intel/avs/topology.h b/sound/soc/intel/avs/topology.h index 304880997717..f5601a4e3ec8 100644 --- a/sound/soc/intel/avs/topology.h +++ b/sound/soc/intel/avs/topology.h @@ -87,7 +87,7 @@ struct avs_tplg_modcfg_ext { struct { u32 out_channel_config; u32 coefficients_select; - s32 coefficients[AVS_CHANNELS_MAX]; + s32 coefficients[AVS_COEFF_CHANNELS_MAX]; u32 channel_map; } updown_mix; struct { diff --git a/sound/soc/intel/avs/utils.h b/sound/soc/intel/avs/utils.h index 5ee569c39380..955a40d2c30c 100644 --- a/sound/soc/intel/avs/utils.h +++ b/sound/soc/intel/avs/utils.h @@ -11,6 +11,16 @@ #include <sound/soc-acpi.h> +extern bool obsolete_card_names; + +struct avs_mach_pdata { + struct hda_codec *codec; + unsigned long *tdms; + char *codec_name; /* DMIC only */ + + bool obsolete_card_names; +}; + static inline bool avs_mach_singular_ssp(struct snd_soc_acpi_mach *mach) { return hweight_long(mach->mach_params.i2s_link_mask) == 1; @@ -23,14 +33,16 @@ static inline u32 avs_mach_ssp_port(struct snd_soc_acpi_mach *mach) static inline bool avs_mach_singular_tdm(struct snd_soc_acpi_mach *mach, u32 port) { - unsigned long *tdms = mach->pdata; + struct avs_mach_pdata *pdata = mach->pdata; + unsigned long *tdms = pdata->tdms; return !tdms || (hweight_long(tdms[port]) == 1); } static inline u32 avs_mach_ssp_tdm(struct snd_soc_acpi_mach *mach, u32 port) { - unsigned long *tdms = mach->pdata; + struct avs_mach_pdata *pdata = mach->pdata; + unsigned long *tdms = pdata->tdms; return tdms ? __ffs(tdms[port]) : 0; } |