diff options
Diffstat (limited to 'sound/soc/intel/avs')
31 files changed, 726 insertions, 342 deletions
diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index 0cf38c9e76..d694e08e44 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -121,6 +121,7 @@ struct avs_dev { struct avs_mods_info *mods_info; struct ida **mod_idas; struct mutex modres_mutex; + void *modcfg_buf; /* module configuration buffer */ struct ida ppl_ida; struct list_head fw_list; int *core_refs; /* reference count per core */ @@ -224,39 +225,22 @@ struct avs_ipc { #define AVS_IPC_RET(ret) \ (((ret) <= 0) ? (ret) : -AVS_EIPC) -static inline void avs_ipc_err(struct avs_dev *adev, struct avs_ipc_msg *tx, - const char *name, int error) -{ - /* - * If IPC channel is blocked e.g.: due to ongoing recovery, - * -EPERM error code is expected and thus it's not an actual error. - * - * Unsupported IPCs are of no harm either. - */ - if (error == -EPERM || error == AVS_IPC_NOT_SUPPORTED) - dev_dbg(adev->dev, "%s 0x%08x 0x%08x failed: %d\n", name, - tx->glb.primary, tx->glb.ext.val, error); - else - dev_err(adev->dev, "%s 0x%08x 0x%08x failed: %d\n", name, - tx->glb.primary, tx->glb.ext.val, error); -} - irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id); irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id); void avs_dsp_process_response(struct avs_dev *adev, u64 header); -int avs_dsp_send_msg_timeout(struct avs_dev *adev, - struct avs_ipc_msg *request, - struct avs_ipc_msg *reply, int timeout); -int avs_dsp_send_msg(struct avs_dev *adev, - struct avs_ipc_msg *request, struct avs_ipc_msg *reply); +int avs_dsp_send_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, + struct avs_ipc_msg *reply, int timeout, const char *name); +int avs_dsp_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request, + struct avs_ipc_msg *reply, const char *name); /* Two variants below are for messages that control DSP power states. */ int avs_dsp_send_pm_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, - struct avs_ipc_msg *reply, int timeout, bool wake_d0i0); + struct avs_ipc_msg *reply, int timeout, bool wake_d0i0, + const char *name); int avs_dsp_send_pm_msg(struct avs_dev *adev, struct avs_ipc_msg *request, - struct avs_ipc_msg *reply, bool wake_d0i0); -int avs_dsp_send_rom_msg_timeout(struct avs_dev *adev, - struct avs_ipc_msg *request, int timeout); -int avs_dsp_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request); + struct avs_ipc_msg *reply, bool wake_d0i0, const char *name); +int avs_dsp_send_rom_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, int timeout, + const char *name); +int avs_dsp_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request, const char *name); void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable); int avs_ipc_init(struct avs_ipc *ipc, struct device *dev); void avs_ipc_block(struct avs_ipc *ipc); diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c index 59a13feec5..8e91eece99 100644 --- a/sound/soc/intel/avs/board_selection.c +++ b/sound/soc/intel/avs/board_selection.c @@ -136,6 +136,15 @@ static struct snd_soc_acpi_mach avs_kbl_i2s_machines[] = { .tplg_filename = "max98927-tplg.bin", }, { + .id = "10EC5514", + .drv_name = "avs_rt5514", + .mach_params = { + .i2s_link_mask = AVS_SSP(0), + }, + .pdata = (unsigned long[]){ 0x2, 0, 0, 0, 0, 0 }, /* SSP0 TDMs */ + .tplg_filename = "rt5514-tplg.bin", + }, + { .id = "10EC5663", .drv_name = "avs_rt5663", .mach_params = { @@ -193,7 +202,7 @@ static struct snd_soc_acpi_mach avs_apl_i2s_machines[] = { .mach_params = { .i2s_link_mask = AVS_SSP_RANGE(0, 5), }, - .pdata = (unsigned long[]){ 0, 0, 0x14, 0, 0, 0 }, /* SSP2 TDMs */ + .pdata = (unsigned long[]){ 0x1, 0x1, 0x14, 0x1, 0x1, 0x1 }, /* SSP2 TDMs */ .tplg_filename = "tdf8532-tplg.bin", }, { diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 07353d37ec..00b0f6c176 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -125,6 +125,16 @@ config SND_SOC_INTEL_AVS_MACH_RT298 Say Y or m if you have such a device. This is a recommended option. If unsure select "N". +config SND_SOC_INTEL_AVS_MACH_RT5514 + tristate "rt5514 in I2S mode" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_RT5514 + help + This adds support for ASoC machine driver with RT5514 I2S audio codec. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + config SND_SOC_INTEL_AVS_MACH_RT5663 tristate "rt5663 in I2S mode" depends on I2C diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index 34347bcd1e..0ff21d55be 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -13,6 +13,7 @@ snd-soc-avs-probe-objs := probe.o snd-soc-avs-rt274-objs := rt274.o snd-soc-avs-rt286-objs := rt286.o snd-soc-avs-rt298-objs := rt298.o +snd-soc-avs-rt5514-objs := rt5514.o snd-soc-avs-rt5663-objs := rt5663.o snd-soc-avs-rt5682-objs := rt5682.o snd-soc-avs-ssm4567-objs := ssm4567.o @@ -30,6 +31,7 @@ obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_PROBE) += snd-soc-avs-probe.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT298) += snd-soc-avs-rt298.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT5514) += snd-soc-avs-rt5514.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT5663) += snd-soc-avs-rt5663.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT5682) += snd-soc-avs-rt5682.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_SSM4567) += snd-soc-avs-ssm4567.o diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c index 85014d98f7..6060894954 100644 --- a/sound/soc/intel/avs/boards/da7219.c +++ b/sound/soc/intel/avs/boards/da7219.c @@ -16,6 +16,7 @@ #include <sound/soc-dapm.h> #include <uapi/linux/input-event-codes.h> #include "../../../codecs/da7219.h" +#include "../utils.h" #define DA7219_DAI_NAME "da7219-hifi" @@ -90,7 +91,7 @@ static const struct snd_soc_jack_pin card_headset_pins[] = { static int avs_da7219_codec_init(struct snd_soc_pcm_runtime *runtime) { - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0); struct snd_soc_component *component = codec_dai->component; struct snd_soc_card *card = runtime->card; struct snd_soc_jack_pin *pins; @@ -140,7 +141,7 @@ static int avs_da7219_codec_init(struct snd_soc_pcm_runtime *runtime) static void avs_da7219_codec_exit(struct snd_soc_pcm_runtime *rtd) { - snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, NULL, NULL); + snd_soc_component_set_jack(snd_soc_rtd_to_codec(rtd, 0)->component, NULL, NULL); } static int @@ -164,7 +165,7 @@ avs_da7219_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_param } static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -177,12 +178,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-DLGS7219:00"); dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, DA7219_DAI_NAME); if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) @@ -230,13 +234,16 @@ static int avs_da7219_probe(struct platform_device *pdev) struct snd_soc_jack *jack; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c index 0a023f871d..f972ef64d2 100644 --- a/sound/soc/intel/avs/boards/es8336.c +++ b/sound/soc/intel/avs/boards/es8336.c @@ -19,6 +19,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <asm/intel-family.h> +#include "../utils.h" #define ES8336_CODEC_DAI "ES8316 HiFi" @@ -97,7 +98,7 @@ static struct snd_soc_jack_pin card_headset_pins[] = { static int avs_es8336_codec_init(struct snd_soc_pcm_runtime *runtime) { - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0); struct snd_soc_component *component = codec_dai->component; struct snd_soc_card *card = runtime->card; struct snd_soc_jack_pin *pins; @@ -138,7 +139,7 @@ static int avs_es8336_codec_init(struct snd_soc_pcm_runtime *runtime) static void avs_es8336_codec_exit(struct snd_soc_pcm_runtime *runtime) { struct avs_card_drvdata *data = snd_soc_card_get_drvdata(runtime->card); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0); snd_soc_component_set_jack(codec_dai->component, NULL, NULL); gpiod_put(data->gpiod); @@ -147,8 +148,8 @@ static void avs_es8336_codec_exit(struct snd_soc_pcm_runtime *runtime) static int avs_es8336_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + struct snd_soc_pcm_runtime *runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0); int clk_freq; int ret; @@ -194,7 +195,7 @@ static int avs_es8336_be_fixup(struct snd_soc_pcm_runtime *runtime, return 0; } static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -206,13 +207,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-ESSX8336:00"); dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, ES8336_CODEC_DAI); if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) @@ -261,13 +264,16 @@ static int avs_es8336_probe(struct platform_device *pdev) struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/i2s_test.c b/sound/soc/intel/avs/boards/i2s_test.c index bc3065c6ce..3d03e1eed3 100644 --- a/sound/soc/intel/avs/boards/i2s_test.c +++ b/sound/soc/intel/avs/boards/i2s_test.c @@ -12,9 +12,10 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> +#include "../utils.h" static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -26,13 +27,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); if (!dl->name || !dl->cpus) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); - dl->codecs = &asoc_dummy_dlc; + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); + dl->codecs = &snd_soc_dummy_dlc; if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) return -ENOMEM; @@ -51,7 +54,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in return 0; } -static int avs_create_dapm_routes(struct device *dev, int ssp_port, +static int avs_create_dapm_routes(struct device *dev, int ssp_port, int tdm_slot, struct snd_soc_dapm_route **routes, int *num_routes) { struct snd_soc_dapm_route *dr; @@ -61,13 +64,17 @@ static int avs_create_dapm_routes(struct device *dev, int ssp_port, if (!dr) return -ENOMEM; - dr[0].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%dpb", ssp_port); - dr[0].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + dr[0].sink = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("ssp", "pb", ssp_port, tdm_slot)); + dr[0].source = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("ssp", " Tx", ssp_port, tdm_slot)); if (!dr[0].sink || !dr[0].source) return -ENOMEM; - dr[1].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port); - dr[1].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%dcp", ssp_port); + dr[1].sink = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("ssp", " Rx", ssp_port, tdm_slot)); + dr[1].source = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("ssp", "cp", ssp_port, tdm_slot)); if (!dr[1].sink || !dr[1].source) return -ENOMEM; @@ -77,7 +84,7 @@ static int avs_create_dapm_routes(struct device *dev, int ssp_port, return 0; } -static int avs_create_dapm_widgets(struct device *dev, int ssp_port, +static int avs_create_dapm_widgets(struct device *dev, int ssp_port, int tdm_slot, struct snd_soc_dapm_widget **widgets, int *num_widgets) { struct snd_soc_dapm_widget *dw; @@ -89,13 +96,15 @@ static int avs_create_dapm_widgets(struct device *dev, int ssp_port, dw[0].id = snd_soc_dapm_hp; dw[0].reg = SND_SOC_NOPM; - dw[0].name = devm_kasprintf(dev, GFP_KERNEL, "ssp%dpb", ssp_port); + dw[0].name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("ssp", "pb", ssp_port, tdm_slot)); if (!dw[0].name) return -ENOMEM; dw[1].id = snd_soc_dapm_mic; dw[1].reg = SND_SOC_NOPM; - dw[1].name = devm_kasprintf(dev, GFP_KERNEL, "ssp%dcp", ssp_port); + dw[1].name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("ssp", "cp", ssp_port, tdm_slot)); if (!dw[1].name) return -ENOMEM; @@ -115,33 +124,45 @@ static int avs_i2s_test_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; const char *pname; int num_routes, num_widgets; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + if (!avs_mach_singular_ssp(mach)) { + dev_err(dev, "Invalid SSP configuration\n"); + return -EINVAL; + } + ssp_port = avs_mach_ssp_port(mach); + + if (!avs_mach_singular_tdm(mach, ssp_port)) { + dev_err(dev, "Invalid TDM configuration\n"); + return -EINVAL; + } + tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; - card->name = devm_kasprintf(dev, GFP_KERNEL, "ssp%d-loopback", ssp_port); + card->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("ssp", "-loopback", ssp_port, tdm_slot)); if (!card->name) return -ENOMEM; - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d\n", ret); return ret; } - ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + ret = avs_create_dapm_routes(dev, ssp_port, tdm_slot, &routes, &num_routes); if (ret) { dev_err(dev, "Failed to create dapm routes: %d\n", ret); return ret; } - ret = avs_create_dapm_widgets(dev, ssp_port, &widgets, &num_widgets); + ret = avs_create_dapm_widgets(dev, ssp_port, tdm_slot, &widgets, &num_widgets); if (ret) { dev_err(dev, "Failed to create dapm widgets: %d\n", ret); return ret; diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c index b9b20562c6..6ba7b65642 100644 --- a/sound/soc/intel/avs/boards/max98357a.c +++ b/sound/soc/intel/avs/boards/max98357a.c @@ -12,6 +12,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> +#include "../utils.h" static const struct snd_kcontrol_new card_controls[] = { SOC_DAPM_PIN_SWITCH("Spk"), @@ -46,7 +47,7 @@ avs_max98357a_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_pa } static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -58,13 +59,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "MX98357A:00"); dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, "HiFi"); if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) @@ -93,13 +96,16 @@ static int avs_max98357a_probe(struct platform_device *pdev) struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/max98373.c b/sound/soc/intel/avs/boards/max98373.c index 3833251ade..cc7dfdf720 100644 --- a/sound/soc/intel/avs/boards/max98373.c +++ b/sound/soc/intel/avs/boards/max98373.c @@ -12,6 +12,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> +#include "../utils.h" #define MAX98373_DEV0_NAME "i2c-MX98373:00" #define MAX98373_DEV1_NAME "i2c-MX98373:01" @@ -66,7 +67,7 @@ avs_max98373_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_par static int avs_max98373_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *runtime = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int ret, i; @@ -95,7 +96,7 @@ static const struct snd_soc_ops avs_max98373_ops = { }; static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -107,13 +108,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs) * 2, GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs[0].name = devm_kasprintf(dev, GFP_KERNEL, MAX98373_DEV0_NAME); dl->codecs[0].dai_name = devm_kasprintf(dev, GFP_KERNEL, MAX98373_CODEC_NAME); dl->codecs[1].name = devm_kasprintf(dev, GFP_KERNEL, MAX98373_DEV1_NAME); @@ -148,13 +151,16 @@ static int avs_max98373_probe(struct platform_device *pdev) struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c index 09b231bf4e..fb0175f37d 100644 --- a/sound/soc/intel/avs/boards/max98927.c +++ b/sound/soc/intel/avs/boards/max98927.c @@ -12,6 +12,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> +#include "../utils.h" #define MAX98927_DEV0_NAME "i2c-MX98927:00" #define MAX98927_DEV1_NAME "i2c-MX98927:01" @@ -66,7 +67,7 @@ avs_max98927_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_par static int avs_max98927_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *runtime = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int ret = 0; int i; @@ -92,7 +93,7 @@ static const struct snd_soc_ops avs_max98927_ops = { }; static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -104,13 +105,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs) * 2, GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs[0].name = devm_kasprintf(dev, GFP_KERNEL, MAX98927_DEV0_NAME); dl->codecs[0].dai_name = devm_kasprintf(dev, GFP_KERNEL, MAX98927_CODEC_NAME); dl->codecs[1].name = devm_kasprintf(dev, GFP_KERNEL, MAX98927_DEV1_NAME); @@ -145,13 +148,16 @@ static int avs_max98927_probe(struct platform_device *pdev) struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c index 38c5087d98..d98b5deb78 100644 --- a/sound/soc/intel/avs/boards/nau8825.c +++ b/sound/soc/intel/avs/boards/nau8825.c @@ -16,6 +16,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include "../../../codecs/nau8825.h" +#include "../utils.h" #define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" @@ -106,12 +107,12 @@ static int avs_nau8825_codec_init(struct snd_soc_pcm_runtime *runtime) snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); - return snd_soc_component_set_jack(asoc_rtd_to_codec(runtime, 0)->component, jack, NULL); + return snd_soc_component_set_jack(snd_soc_rtd_to_codec(runtime, 0)->component, jack, NULL); } static void avs_nau8825_codec_exit(struct snd_soc_pcm_runtime *rtd) { - snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, NULL, NULL); + snd_soc_component_set_jack(snd_soc_rtd_to_codec(rtd, 0)->component, NULL, NULL); } static int @@ -138,8 +139,8 @@ avs_nau8825_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_para static int avs_nau8825_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtm = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtm, 0); + struct snd_soc_pcm_runtime *rtm = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtm, 0); int ret = 0; switch (cmd) { @@ -171,7 +172,7 @@ static const struct snd_soc_ops avs_nau8825_ops = { }; static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -183,13 +184,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-10508825:00"); dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, SKL_NUVOTON_CODEC_DAI); if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) @@ -248,13 +251,16 @@ static int avs_nau8825_probe(struct platform_device *pdev) struct snd_soc_jack *jack; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c index ebfee54814..157183b1de 100644 --- a/sound/soc/intel/avs/boards/rt274.c +++ b/sound/soc/intel/avs/boards/rt274.c @@ -13,6 +13,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include "../../../codecs/rt274.h" +#include "../utils.h" #define AVS_RT274_FREQ_OUT 24000000 #define AVS_RT274_BE_FIXUP_RATE 48000 @@ -87,7 +88,7 @@ static struct snd_soc_jack_pin card_headset_pins[] = { static int avs_rt274_codec_init(struct snd_soc_pcm_runtime *runtime) { - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0); struct snd_soc_component *component = codec_dai->component; struct snd_soc_jack_pin *pins; struct snd_soc_jack *jack; @@ -121,7 +122,7 @@ static int avs_rt274_codec_init(struct snd_soc_pcm_runtime *runtime) static void avs_rt274_codec_exit(struct snd_soc_pcm_runtime *rtd) { - snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, NULL, NULL); + snd_soc_component_set_jack(snd_soc_rtd_to_codec(rtd, 0)->component, NULL, NULL); } static int avs_rt274_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_params *params) @@ -145,7 +146,7 @@ static int avs_rt274_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pc } static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -157,13 +158,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-INT34C2:00"); dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, RT274_CODEC_DAI); if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) @@ -211,13 +214,16 @@ static int avs_rt274_probe(struct platform_device *pdev) struct snd_soc_jack *jack; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c index 84cf9a0c8d..131237471e 100644 --- a/sound/soc/intel/avs/boards/rt286.c +++ b/sound/soc/intel/avs/boards/rt286.c @@ -13,6 +13,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include "../../../codecs/rt286.h" +#include "../utils.h" #define RT286_CODEC_DAI "rt286-aif1" @@ -67,12 +68,12 @@ static int avs_rt286_codec_init(struct snd_soc_pcm_runtime *runtime) if (ret) return ret; - return snd_soc_component_set_jack(asoc_rtd_to_codec(runtime, 0)->component, jack, NULL); + return snd_soc_component_set_jack(snd_soc_rtd_to_codec(runtime, 0)->component, jack, NULL); } static void avs_rt286_codec_exit(struct snd_soc_pcm_runtime *rtd) { - snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, NULL, NULL); + snd_soc_component_set_jack(snd_soc_rtd_to_codec(rtd, 0)->component, NULL, NULL); } static int avs_rt286_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_params *params) @@ -98,8 +99,8 @@ static int avs_rt286_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pc static int avs_rt286_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + struct snd_soc_pcm_runtime *runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000, SND_SOC_CLOCK_IN); @@ -114,7 +115,7 @@ static const struct snd_soc_ops avs_rt286_ops = { }; static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -126,13 +127,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-INT343A:00"); dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, RT286_CODEC_DAI); if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) @@ -181,13 +184,17 @@ static int avs_rt286_probe(struct platform_device *pdev) struct snd_soc_jack *jack; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c index 3b0e2b1a32..ea32a7690c 100644 --- a/sound/soc/intel/avs/boards/rt298.c +++ b/sound/soc/intel/avs/boards/rt298.c @@ -14,6 +14,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include "../../../codecs/rt298.h" +#include "../utils.h" #define RT298_CODEC_DAI "rt298-aif1" @@ -78,12 +79,12 @@ static int avs_rt298_codec_init(struct snd_soc_pcm_runtime *runtime) if (ret) return ret; - return snd_soc_component_set_jack(asoc_rtd_to_codec(runtime, 0)->component, jack, NULL); + return snd_soc_component_set_jack(snd_soc_rtd_to_codec(runtime, 0)->component, jack, NULL); } static void avs_rt298_codec_exit(struct snd_soc_pcm_runtime *rtd) { - snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, NULL, NULL); + snd_soc_component_set_jack(snd_soc_rtd_to_codec(rtd, 0)->component, NULL, NULL); } static int avs_rt298_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_params *params) @@ -109,8 +110,8 @@ static int avs_rt298_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pc static int avs_rt298_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); unsigned int clk_freq; int ret; @@ -131,7 +132,7 @@ static const struct snd_soc_ops avs_rt298_ops = { }; static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -143,13 +144,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-INT343A:00"); dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, RT298_CODEC_DAI); if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) @@ -201,13 +204,16 @@ static int avs_rt298_probe(struct platform_device *pdev) struct snd_soc_jack *jack; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/rt5514.c b/sound/soc/intel/avs/boards/rt5514.c new file mode 100644 index 0000000000..ad486a52e5 --- /dev/null +++ b/sound/soc/intel/avs/boards/rt5514.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2023 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski <cezary.rojewski@intel.com> +// Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> +// + +#include <linux/clk.h> +#include <linux/input.h> +#include <linux/module.h> +#include <sound/jack.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "../../../codecs/rt5514.h" +#include "../utils.h" + +#define RT5514_CODEC_DAI "rt5514-aif1" + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_MIC("DMIC", NULL), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + /* DMIC */ + { "DMIC1L", NULL, "DMIC" }, + { "DMIC1R", NULL, "DMIC" }, + { "DMIC2L", NULL, "DMIC" }, + { "DMIC2R", NULL, "DMIC" }, +}; + +static int avs_rt5514_codec_init(struct snd_soc_pcm_runtime *runtime) +{ + int ret = snd_soc_dapm_ignore_suspend(&runtime->card->dapm, "DMIC"); + + if (ret) + dev_err(runtime->dev, "DMIC - Ignore suspend failed = %d\n", ret); + + return ret; +} + +static int avs_rt5514_be_fixup(struct snd_soc_pcm_runtime *runtime, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + rate->min = rate->max = 48000; + channels->min = channels->max = 4; + + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + + return 0; +} + +static int avs_rt5514_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + int ret; + + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0, 8, 16); + if (ret < 0) { + dev_err(rtd->dev, "set TDM slot err:%d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(rtd->dev, "set sysclk err: %d\n", ret); + + return ret; +} + +static const struct snd_soc_ops avs_rt5514_ops = { + .hw_params = avs_rt5514_hw_params, +}; + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + int tdm_slot, struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); + dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-10EC5514:00"); + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, RT5514_CODEC_DAI); + if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 1; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->init = avs_rt5514_codec_init; + dl->be_hw_params_fixup = avs_rt5514_be_fixup; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->ops = &avs_rt5514_ops; + + *dai_link = dl; + + return 0; +} + +static int avs_rt5514_probe(struct platform_device *pdev) +{ + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct device *dev = &pdev->dev; + const char *pname; + int ssp_port, tdm_slot, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->name = "avs_rt5514"; + card->dev = dev; + card->owner = THIS_MODULE; + card->dai_link = dai_link; + card->num_links = 1; + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = card_base_routes; + card->num_dapm_routes = ARRAY_SIZE(card_base_routes); + card->fully_routed = true; + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_rt5514_driver = { + .probe = avs_rt5514_probe, + .driver = { + .name = "avs_rt5514", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_rt5514_driver); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_rt5514"); diff --git a/sound/soc/intel/avs/boards/rt5663.c b/sound/soc/intel/avs/boards/rt5663.c index 770b36d05b..3effd789a4 100644 --- a/sound/soc/intel/avs/boards/rt5663.c +++ b/sound/soc/intel/avs/boards/rt5663.c @@ -15,6 +15,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include "../../../codecs/rt5663.h" +#include "../utils.h" #define RT5663_CODEC_DAI "rt5663-aif" @@ -79,14 +80,14 @@ static int avs_rt5663_codec_init(struct snd_soc_pcm_runtime *runtime) snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); - snd_soc_component_set_jack(asoc_rtd_to_codec(runtime, 0)->component, jack, NULL); + snd_soc_component_set_jack(snd_soc_rtd_to_codec(runtime, 0)->component, jack, NULL); return 0; } static void avs_rt5663_codec_exit(struct snd_soc_pcm_runtime *runtime) { - snd_soc_component_set_jack(asoc_rtd_to_codec(runtime, 0)->component, NULL, NULL); + snd_soc_component_set_jack(snd_soc_rtd_to_codec(runtime, 0)->component, NULL, NULL); } static int @@ -113,8 +114,8 @@ avs_rt5663_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_param static int avs_rt5663_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); int ret; /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ @@ -133,7 +134,7 @@ static const struct snd_soc_ops avs_rt5663_ops = { static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -145,13 +146,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-10EC5663:00"); dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, RT5663_CODEC_DAI); if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) @@ -200,13 +203,16 @@ static int avs_rt5663_probe(struct platform_device *pdev) struct rt5663_private *priv; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c index b93468ae09..84e850c0b0 100644 --- a/sound/soc/intel/avs/boards/rt5682.c +++ b/sound/soc/intel/avs/boards/rt5682.c @@ -21,6 +21,7 @@ #include <sound/soc-acpi.h> #include "../../common/soc-intel-quirks.h" #include "../../../codecs/rt5682.h" +#include "../utils.h" #define AVS_RT5682_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0)) #define AVS_RT5682_SSP_CODEC_MASK (GENMASK(2, 0)) @@ -92,7 +93,7 @@ static struct snd_soc_jack_pin card_jack_pins[] = { static int avs_rt5682_codec_init(struct snd_soc_pcm_runtime *runtime) { - struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; + struct snd_soc_component *component = snd_soc_rtd_to_codec(runtime, 0)->component; struct snd_soc_card *card = runtime->card; struct snd_soc_jack_pin *pins; struct snd_soc_jack *jack; @@ -137,14 +138,14 @@ static int avs_rt5682_codec_init(struct snd_soc_pcm_runtime *runtime) static void avs_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd) { - snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, NULL, NULL); + snd_soc_component_set_jack(snd_soc_rtd_to_codec(rtd, 0)->component, NULL, NULL); } static int avs_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + struct snd_soc_pcm_runtime *runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0); int pll_source, freq_in, freq_out; int ret; @@ -203,7 +204,7 @@ avs_rt5682_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_param } static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -215,13 +216,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-10EC5682:00"); dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, AVS_RT5682_CODEC_DAI_NAME); if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) @@ -270,7 +273,7 @@ static int avs_rt5682_probe(struct platform_device *pdev) struct snd_soc_jack *jack; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; if (pdev->id_entry && pdev->id_entry->driver_data) avs_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data; @@ -280,9 +283,12 @@ static int avs_rt5682_probe(struct platform_device *pdev) mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c index 7324869d61..6bcab9deae 100644 --- a/sound/soc/intel/avs/boards/ssm4567.c +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -14,6 +14,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include "../../../codecs/nau8825.h" +#include "../utils.h" #define SKL_SSM_CODEC_DAI "ssm4567-hifi" @@ -50,12 +51,12 @@ static int avs_ssm4567_codec_init(struct snd_soc_pcm_runtime *runtime) int ret; /* Slot 1 for left */ - ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(runtime, 0), 0x01, 0x01, 2, 48); + ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_codec(runtime, 0), 0x01, 0x01, 2, 48); if (ret < 0) return ret; /* Slot 2 for right */ - ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(runtime, 1), 0x02, 0x02, 2, 48); + ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_codec(runtime, 1), 0x02, 0x02, 2, 48); if (ret < 0) return ret; @@ -83,7 +84,7 @@ avs_ssm4567_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_para } static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, - struct snd_soc_dai_link **dai_link) + int tdm_slot, struct snd_soc_dai_link **dai_link) { struct snd_soc_dai_link_component *platform; struct snd_soc_dai_link *dl; @@ -95,13 +96,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in platform->name = platform_name; - dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs) * 2, GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; - dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); dl->codecs[0].name = devm_kasprintf(dev, GFP_KERNEL, "i2c-INT343B:00"); dl->codecs[0].dai_name = devm_kasprintf(dev, GFP_KERNEL, "ssm4567-hifi"); dl->codecs[1].name = devm_kasprintf(dev, GFP_KERNEL, "i2c-INT343B:01"); @@ -136,13 +139,16 @@ static int avs_ssm4567_probe(struct platform_device *pdev) struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; - int ssp_port, ret; + int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); pname = mach->mach_params.platform; - ssp_port = __ffs(mach->mach_params.i2s_link_mask); - ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); + if (ret) + return ret; + + ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link); if (ret) { dev_err(dev, "Failed to create dai link: %d", ret); return ret; diff --git a/sound/soc/intel/avs/cldma.h b/sound/soc/intel/avs/cldma.h index 754fcf9ee5..223d3431ab 100644 --- a/sound/soc/intel/avs/cldma.h +++ b/sound/soc/intel/avs/cldma.h @@ -8,7 +8,9 @@ #ifndef __SOUND_SOC_INTEL_AVS_CLDMA_H #define __SOUND_SOC_INTEL_AVS_CLDMA_H -#define AVS_CL_DEFAULT_BUFFER_SIZE (32 * PAGE_SIZE) +#include <linux/sizes.h> + +#define AVS_CL_DEFAULT_BUFFER_SIZE SZ_128K struct hda_cldma; extern struct hda_cldma code_loader; diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index 859b217fc7..db78eb2f01 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -26,6 +26,7 @@ #include "../../codecs/hda.h" #include "avs.h" #include "cldma.h" +#include "messages.h" static u32 pgctl_mask = AZX_PGCTL_LSRMD_MASK; module_param(pgctl_mask, uint, 0444); @@ -191,10 +192,6 @@ static void avs_hda_probe_work(struct work_struct *work) pm_runtime_set_active(bus->dev); /* clear runtime_error flag */ - ret = snd_hdac_i915_init(bus); - if (ret < 0) - dev_info(bus->dev, "i915 init unsuccessful: %d\n", ret); - snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); avs_hdac_bus_init_chip(bus, true); avs_hdac_bus_probe_codecs(bus); @@ -380,6 +377,10 @@ static int avs_bus_init(struct avs_dev *adev, struct pci_dev *pci, const struct if (ret < 0) return ret; + adev->modcfg_buf = devm_kzalloc(dev, AVS_MAILBOX_SIZE, GFP_KERNEL); + if (!adev->modcfg_buf) + return -ENOMEM; + adev->dev = dev; adev->spec = (const struct avs_spec *)id->driver_data; adev->ipc = ipc; @@ -465,10 +466,22 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) pci_set_drvdata(pci, bus); device_disable_async_suspend(dev); + ret = snd_hdac_i915_init(bus); + if (ret == -EPROBE_DEFER) + goto err_i915_init; + else if (ret < 0) + dev_info(bus->dev, "i915 init unsuccessful: %d\n", ret); + schedule_work(&adev->probe_work); return 0; +err_i915_init: + pci_free_irq(pci, 0, adev); + pci_free_irq(pci, 0, bus); + pci_free_irq_vectors(pci); + pci_clear_master(pci); + pci_set_drvdata(pci, NULL); err_acquire_irq: snd_hdac_bus_free_stream_pages(bus); snd_hdac_ext_stream_free_all(bus); diff --git a/sound/soc/intel/avs/debugfs.c b/sound/soc/intel/avs/debugfs.c index bdd388ec01..4dfbff0ce5 100644 --- a/sound/soc/intel/avs/debugfs.c +++ b/sound/soc/intel/avs/debugfs.c @@ -236,6 +236,9 @@ static int strace_open(struct inode *inode, struct file *file) struct avs_dev *adev = inode->i_private; int ret; + if (!try_module_get(adev->dev->driver->owner)) + return -ENODEV; + if (kfifo_initialized(&adev->trace_fifo)) return -EBUSY; @@ -270,6 +273,7 @@ static int strace_release(struct inode *inode, struct file *file) spin_unlock_irqrestore(&adev->trace_lock, flags); + module_put(adev->dev->driver->owner); return 0; } diff --git a/sound/soc/intel/avs/ipc.c b/sound/soc/intel/avs/ipc.c index bdf013c3dd..65bfc83bd1 100644 --- a/sound/soc/intel/avs/ipc.c +++ b/sound/soc/intel/avs/ipc.c @@ -455,7 +455,7 @@ static void avs_dsp_send_tx(struct avs_dev *adev, struct avs_ipc_msg *tx, bool r } static int avs_dsp_do_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request, - struct avs_ipc_msg *reply, int timeout) + struct avs_ipc_msg *reply, int timeout, const char *name) { struct avs_ipc *ipc = adev->ipc; int ret; @@ -482,6 +482,19 @@ static int avs_dsp_do_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request } ret = ipc->rx.rsp.status; + /* + * If IPC channel is blocked e.g.: due to ongoing recovery, + * -EPERM error code is expected and thus it's not an actual error. + * + * Unsupported IPCs are of no harm either. + */ + if (ret == -EPERM || ret == AVS_IPC_NOT_SUPPORTED) + dev_dbg(adev->dev, "%s (0x%08x 0x%08x) failed: %d\n", + name, request->glb.primary, request->glb.ext.val, ret); + else if (ret) + dev_err(adev->dev, "%s (0x%08x 0x%08x) failed: %d\n", + name, request->glb.primary, request->glb.ext.val, ret); + if (reply) { reply->header = ipc->rx.header; reply->size = ipc->rx.size; @@ -496,7 +509,7 @@ exit: static int avs_dsp_send_msg_sequence(struct avs_dev *adev, struct avs_ipc_msg *request, struct avs_ipc_msg *reply, int timeout, bool wake_d0i0, - bool schedule_d0ix) + bool schedule_d0ix, const char *name) { int ret; @@ -507,7 +520,7 @@ static int avs_dsp_send_msg_sequence(struct avs_dev *adev, struct avs_ipc_msg *r return ret; } - ret = avs_dsp_do_send_msg(adev, request, reply, timeout); + ret = avs_dsp_do_send_msg(adev, request, reply, timeout, name); if (ret) return ret; @@ -519,34 +532,37 @@ static int avs_dsp_send_msg_sequence(struct avs_dev *adev, struct avs_ipc_msg *r } int avs_dsp_send_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, - struct avs_ipc_msg *reply, int timeout) + struct avs_ipc_msg *reply, int timeout, const char *name) { bool wake_d0i0 = avs_dsp_op(adev, d0ix_toggle, request, true); bool schedule_d0ix = avs_dsp_op(adev, d0ix_toggle, request, false); - return avs_dsp_send_msg_sequence(adev, request, reply, timeout, wake_d0i0, schedule_d0ix); + return avs_dsp_send_msg_sequence(adev, request, reply, timeout, wake_d0i0, schedule_d0ix, + name); } int avs_dsp_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request, - struct avs_ipc_msg *reply) + struct avs_ipc_msg *reply, const char *name) { - return avs_dsp_send_msg_timeout(adev, request, reply, adev->ipc->default_timeout_ms); + return avs_dsp_send_msg_timeout(adev, request, reply, adev->ipc->default_timeout_ms, name); } int avs_dsp_send_pm_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, - struct avs_ipc_msg *reply, int timeout, bool wake_d0i0) + struct avs_ipc_msg *reply, int timeout, bool wake_d0i0, + const char *name) { - return avs_dsp_send_msg_sequence(adev, request, reply, timeout, wake_d0i0, false); + return avs_dsp_send_msg_sequence(adev, request, reply, timeout, wake_d0i0, false, name); } int avs_dsp_send_pm_msg(struct avs_dev *adev, struct avs_ipc_msg *request, - struct avs_ipc_msg *reply, bool wake_d0i0) + struct avs_ipc_msg *reply, bool wake_d0i0, const char *name) { return avs_dsp_send_pm_msg_timeout(adev, request, reply, adev->ipc->default_timeout_ms, - wake_d0i0); + wake_d0i0, name); } -static int avs_dsp_do_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request, int timeout) +static int avs_dsp_do_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request, int timeout, + const char *name) { struct avs_ipc *ipc = adev->ipc; int ret; @@ -568,20 +584,24 @@ static int avs_dsp_do_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *req ret = wait_for_completion_timeout(&ipc->done_completion, msecs_to_jiffies(timeout)); ret = ret ? 0 : -ETIMEDOUT; } + if (ret) + dev_err(adev->dev, "%s (0x%08x 0x%08x) failed: %d\n", + name, request->glb.primary, request->glb.ext.val, ret); mutex_unlock(&ipc->msg_mutex); return ret; } -int avs_dsp_send_rom_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, int timeout) +int avs_dsp_send_rom_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, int timeout, + const char *name) { - return avs_dsp_do_send_rom_msg(adev, request, timeout); + return avs_dsp_do_send_rom_msg(adev, request, timeout, name); } -int avs_dsp_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request) +int avs_dsp_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request, const char *name) { - return avs_dsp_send_rom_msg_timeout(adev, request, adev->ipc->default_timeout_ms); + return avs_dsp_send_rom_msg_timeout(adev, request, adev->ipc->default_timeout_ms, name); } void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable) diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c index 56bb0a5924..65dd8f140f 100644 --- a/sound/soc/intel/avs/loader.c +++ b/sound/soc/intel/avs/loader.c @@ -662,6 +662,10 @@ int avs_dsp_first_boot_firmware(struct avs_dev *adev) } } + ret = avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK); + if (ret < 0) + return ret; + ret = avs_dsp_boot_firmware(adev, true); if (ret < 0) { dev_err(adev->dev, "firmware boot failed: %d\n", ret); diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index f887ab5b03..06b4394cab 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -16,71 +16,52 @@ int avs_ipc_set_boot_config(struct avs_dev *adev, u32 dma_id, u32 purge) { union avs_global_msg msg = AVS_GLOBAL_REQUEST(ROM_CONTROL); struct avs_ipc_msg request = {{0}}; - int ret; msg.boot_cfg.rom_ctrl_msg_type = AVS_ROM_SET_BOOT_CONFIG; msg.boot_cfg.dma_id = dma_id; msg.boot_cfg.purge_request = purge; request.header = msg.val; - ret = avs_dsp_send_rom_msg(adev, &request); - if (ret) - avs_ipc_err(adev, &request, "set boot config", ret); - - return ret; + return avs_dsp_send_rom_msg(adev, &request, "set boot config"); } int avs_ipc_load_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids) { union avs_global_msg msg = AVS_GLOBAL_REQUEST(LOAD_MULTIPLE_MODULES); struct avs_ipc_msg request; - int ret; msg.load_multi_mods.mod_cnt = num_mod_ids; request.header = msg.val; request.data = mod_ids; request.size = sizeof(*mod_ids) * num_mod_ids; - ret = avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS); - if (ret) - avs_ipc_err(adev, &request, "load multiple modules", ret); - - return ret; + return avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS, + "load multiple modules"); } int avs_ipc_unload_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids) { union avs_global_msg msg = AVS_GLOBAL_REQUEST(UNLOAD_MULTIPLE_MODULES); struct avs_ipc_msg request; - int ret; msg.load_multi_mods.mod_cnt = num_mod_ids; request.header = msg.val; request.data = mod_ids; request.size = sizeof(*mod_ids) * num_mod_ids; - ret = avs_dsp_send_msg(adev, &request, NULL); - if (ret) - avs_ipc_err(adev, &request, "unload multiple modules", ret); - - return ret; + return avs_dsp_send_msg(adev, &request, NULL, "unload multiple modules"); } int avs_ipc_load_library(struct avs_dev *adev, u32 dma_id, u32 lib_id) { union avs_global_msg msg = AVS_GLOBAL_REQUEST(LOAD_LIBRARY); struct avs_ipc_msg request = {{0}}; - int ret; msg.load_lib.dma_id = dma_id; msg.load_lib.lib_id = lib_id; request.header = msg.val; - ret = avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS); - if (ret) - avs_ipc_err(adev, &request, "load library", ret); - - return ret; + return avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS, "load library"); } int avs_ipc_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority, @@ -88,7 +69,6 @@ int avs_ipc_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority, { union avs_global_msg msg = AVS_GLOBAL_REQUEST(CREATE_PIPELINE); struct avs_ipc_msg request = {{0}}; - int ret; msg.create_ppl.ppl_mem_size = req_size; msg.create_ppl.ppl_priority = priority; @@ -97,27 +77,18 @@ int avs_ipc_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority, msg.ext.create_ppl.attributes = attributes; request.header = msg.val; - ret = avs_dsp_send_msg(adev, &request, NULL); - if (ret) - avs_ipc_err(adev, &request, "create pipeline", ret); - - return ret; + return avs_dsp_send_msg(adev, &request, NULL, "create pipeline"); } int avs_ipc_delete_pipeline(struct avs_dev *adev, u8 instance_id) { union avs_global_msg msg = AVS_GLOBAL_REQUEST(DELETE_PIPELINE); struct avs_ipc_msg request = {{0}}; - int ret; msg.ppl.instance_id = instance_id; request.header = msg.val; - ret = avs_dsp_send_msg(adev, &request, NULL); - if (ret) - avs_ipc_err(adev, &request, "delete pipeline", ret); - - return ret; + return avs_dsp_send_msg(adev, &request, NULL, "delete pipeline"); } int avs_ipc_set_pipeline_state(struct avs_dev *adev, u8 instance_id, @@ -125,17 +96,12 @@ int avs_ipc_set_pipeline_state(struct avs_dev *adev, u8 instance_id, { union avs_global_msg msg = AVS_GLOBAL_REQUEST(SET_PIPELINE_STATE); struct avs_ipc_msg request = {{0}}; - int ret; msg.set_ppl_state.ppl_id = instance_id; msg.set_ppl_state.state = state; request.header = msg.val; - ret = avs_dsp_send_msg(adev, &request, NULL); - if (ret) - avs_ipc_err(adev, &request, "set pipeline state", ret); - - return ret; + return avs_dsp_send_msg(adev, &request, NULL, "set pipeline state"); } int avs_ipc_get_pipeline_state(struct avs_dev *adev, u8 instance_id, @@ -149,13 +115,9 @@ int avs_ipc_get_pipeline_state(struct avs_dev *adev, u8 instance_id, msg.get_ppl_state.ppl_id = instance_id; request.header = msg.val; - ret = avs_dsp_send_msg(adev, &request, &reply); - if (ret) { - avs_ipc_err(adev, &request, "get pipeline state", ret); - return ret; - } - - *state = reply.rsp.ext.get_ppl_state.state; + ret = avs_dsp_send_msg(adev, &request, &reply, "get pipeline state"); + if (!ret) + *state = reply.rsp.ext.get_ppl_state.state; return ret; } @@ -183,7 +145,6 @@ int avs_ipc_init_instance(struct avs_dev *adev, u16 module_id, u8 instance_id, { union avs_module_msg msg = AVS_MODULE_REQUEST(INIT_INSTANCE); struct avs_ipc_msg request; - int ret; msg.module_id = module_id; msg.instance_id = instance_id; @@ -197,11 +158,7 @@ int avs_ipc_init_instance(struct avs_dev *adev, u16 module_id, u8 instance_id, request.data = param; request.size = param_size; - ret = avs_dsp_send_msg(adev, &request, NULL); - if (ret) - avs_ipc_err(adev, &request, "init instance", ret); - - return ret; + return avs_dsp_send_msg(adev, &request, NULL, "init instance"); } /* @@ -222,17 +179,12 @@ int avs_ipc_delete_instance(struct avs_dev *adev, u16 module_id, u8 instance_id) { union avs_module_msg msg = AVS_MODULE_REQUEST(DELETE_INSTANCE); struct avs_ipc_msg request = {{0}}; - int ret; msg.module_id = module_id; msg.instance_id = instance_id; request.header = msg.val; - ret = avs_dsp_send_msg(adev, &request, NULL); - if (ret) - avs_ipc_err(adev, &request, "delete instance", ret); - - return ret; + return avs_dsp_send_msg(adev, &request, NULL, "delete instance"); } /* @@ -252,7 +204,6 @@ int avs_ipc_bind(struct avs_dev *adev, u16 module_id, u8 instance_id, { union avs_module_msg msg = AVS_MODULE_REQUEST(BIND); struct avs_ipc_msg request = {{0}}; - int ret; msg.module_id = module_id; msg.instance_id = instance_id; @@ -262,11 +213,7 @@ int avs_ipc_bind(struct avs_dev *adev, u16 module_id, u8 instance_id, msg.ext.bind_unbind.src_queue = src_queue; request.header = msg.val; - ret = avs_dsp_send_msg(adev, &request, NULL); - if (ret) - avs_ipc_err(adev, &request, "bind modules", ret); - - return ret; + return avs_dsp_send_msg(adev, &request, NULL, "bind modules"); } /* @@ -286,7 +233,6 @@ int avs_ipc_unbind(struct avs_dev *adev, u16 module_id, u8 instance_id, { union avs_module_msg msg = AVS_MODULE_REQUEST(UNBIND); struct avs_ipc_msg request = {{0}}; - int ret; msg.module_id = module_id; msg.instance_id = instance_id; @@ -296,11 +242,7 @@ int avs_ipc_unbind(struct avs_dev *adev, u16 module_id, u8 instance_id, msg.ext.bind_unbind.src_queue = src_queue; request.header = msg.val; - ret = avs_dsp_send_msg(adev, &request, NULL); - if (ret) - avs_ipc_err(adev, &request, "unbind modules", ret); - - return ret; + return avs_dsp_send_msg(adev, &request, NULL, "unbind modules"); } static int __avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id, @@ -309,7 +251,6 @@ static int __avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id, u8 in { union avs_module_msg msg = AVS_MODULE_REQUEST(LARGE_CONFIG_SET); struct avs_ipc_msg request; - int ret; msg.module_id = module_id; msg.instance_id = instance_id; @@ -322,11 +263,7 @@ static int __avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id, u8 in request.data = request_data; request.size = request_size; - ret = avs_dsp_send_msg(adev, &request, NULL); - if (ret) - avs_ipc_err(adev, &request, "large config set", ret); - - return ret; + return avs_dsp_send_msg(adev, &request, NULL, "large config set"); } int avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id, @@ -398,9 +335,8 @@ int avs_ipc_get_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id request.size = request_size; reply.size = AVS_MAILBOX_SIZE; - ret = avs_dsp_send_msg(adev, &request, &reply); + ret = avs_dsp_send_msg(adev, &request, &reply, "large config get"); if (ret) { - avs_ipc_err(adev, &request, "large config get", ret); kfree(reply.data); return ret; } @@ -422,7 +358,6 @@ int avs_ipc_set_dx(struct avs_dev *adev, u32 core_mask, bool powerup) union avs_module_msg msg = AVS_MODULE_REQUEST(SET_DX); struct avs_ipc_msg request; struct avs_dxstate_info dx; - int ret; dx.core_mask = core_mask; dx.dx_mask = powerup ? core_mask : 0; @@ -430,11 +365,7 @@ int avs_ipc_set_dx(struct avs_dev *adev, u32 core_mask, bool powerup) request.data = &dx; request.size = sizeof(dx); - ret = avs_dsp_send_pm_msg(adev, &request, NULL, true); - if (ret) - avs_ipc_err(adev, &request, "set dx", ret); - - return ret; + return avs_dsp_send_pm_msg(adev, &request, NULL, true, "set dx"); } /* @@ -447,18 +378,13 @@ int avs_ipc_set_d0ix(struct avs_dev *adev, bool enable_pg, bool streaming) { union avs_module_msg msg = AVS_MODULE_REQUEST(SET_D0IX); struct avs_ipc_msg request = {{0}}; - int ret; msg.ext.set_d0ix.wake = enable_pg; msg.ext.set_d0ix.streaming = streaming; request.header = msg.val; - ret = avs_dsp_send_pm_msg(adev, &request, NULL, false); - if (ret) - avs_ipc_err(adev, &request, "set d0ix", ret); - - return ret; + return avs_dsp_send_pm_msg(adev, &request, NULL, false, "set d0ix"); } int avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg) diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 7f23a304b4..d0344e242e 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -9,9 +9,11 @@ #ifndef __SOUND_SOC_INTEL_AVS_MSGS_H #define __SOUND_SOC_INTEL_AVS_MSGS_H +#include <linux/sizes.h> + struct avs_dev; -#define AVS_MAILBOX_SIZE 4096 +#define AVS_MAILBOX_SIZE SZ_4K enum avs_msg_target { AVS_FW_GEN_MSG = 0, diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index adbe23a478..aa8b50b931 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -237,11 +237,11 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) /* Every config-BLOB contains gateway attributes. */ if (data_size) cfg_size -= sizeof(cfg->gtw_cfg.config.attrs); + if (cfg_size > AVS_MAILBOX_SIZE) + return -EINVAL; - cfg = kzalloc(cfg_size, GFP_KERNEL); - if (!cfg) - return -ENOMEM; - + cfg = adev->modcfg_buf; + memset(cfg, 0, cfg_size); cfg->base.cpc = t->cfg_base->cpc; cfg->base.ibs = t->cfg_base->ibs; cfg->base.obs = t->cfg_base->obs; @@ -261,7 +261,6 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id, t->domain, cfg, cfg_size, &mod->instance_id); - kfree(cfg); return ret; } @@ -294,7 +293,7 @@ static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod) struct avs_control_data *ctl_data; struct avs_peakvol_cfg *cfg; int volume = S32_MAX; - size_t size; + size_t cfg_size; int ret; ctl_data = avs_get_module_control(mod); @@ -302,11 +301,12 @@ static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod) volume = ctl_data->volume; /* As 2+ channels controls are unsupported, have a single block for all channels. */ - size = struct_size(cfg, vols, 1); - cfg = kzalloc(size, GFP_KERNEL); - if (!cfg) - return -ENOMEM; + cfg_size = struct_size(cfg, vols, 1); + if (cfg_size > AVS_MAILBOX_SIZE) + return -EINVAL; + cfg = adev->modcfg_buf; + memset(cfg, 0, cfg_size); cfg->base.cpc = t->cfg_base->cpc; cfg->base.ibs = t->cfg_base->ibs; cfg->base.obs = t->cfg_base->obs; @@ -318,9 +318,8 @@ static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod) cfg->vols[0].curve_duration = 0; ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id, - t->domain, cfg, size, &mod->instance_id); + t->domain, cfg, cfg_size, &mod->instance_id); - kfree(cfg); return ret; } @@ -480,10 +479,11 @@ static int avs_modext_create(struct avs_dev *adev, struct avs_path_module *mod) num_pins = tcfg->generic.num_input_pins + tcfg->generic.num_output_pins; cfg_size = struct_size(cfg, pin_fmts, num_pins); - cfg = kzalloc(cfg_size, GFP_KERNEL); - if (!cfg) - return -ENOMEM; + if (cfg_size > AVS_MAILBOX_SIZE) + return -EINVAL; + cfg = adev->modcfg_buf; + memset(cfg, 0, cfg_size); cfg->base.cpc = t->cfg_base->cpc; cfg->base.ibs = t->cfg_base->ibs; cfg->base.obs = t->cfg_base->obs; @@ -505,7 +505,6 @@ static int avs_modext_create(struct avs_dev *adev, struct avs_path_module *mod) ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id, t->domain, cfg, cfg_size, &mod->instance_id); - kfree(cfg); return ret; } diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 8565a53070..463dbba184 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -58,7 +58,7 @@ avs_dai_find_path_template(struct snd_soc_dai *dai, bool is_fe, int direction) static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, bool is_fe, const struct snd_soc_dai_ops *ops) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct avs_dev *adev = to_avs_dev(dai->dev); struct avs_tplg_path_template *template; struct avs_dma_data *data; @@ -127,7 +127,7 @@ static int avs_dai_be_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *fe, *be; struct snd_soc_dpcm *dpcm; - be = asoc_substream_to_rtd(substream); + be = snd_soc_substream_to_rtd(substream); for_each_dpcm_fe(be, substream->stream, dpcm) { fe = dpcm->fe; fe_hw_params = &fe->dpcm[substream->stream].hw_params; @@ -167,7 +167,7 @@ static int avs_dai_nonhda_be_startup(struct snd_pcm_substream *substream, struct static void avs_dai_nonhda_be_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct avs_dev *adev = to_avs_dev(dai->dev); struct avs_dma_data *data; @@ -216,7 +216,7 @@ static int avs_dai_nonhda_be_prepare(struct snd_pcm_substream *substream, struct static int avs_dai_nonhda_be_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct avs_dma_data *data; int ret = 0; @@ -303,7 +303,7 @@ static int avs_dai_hda_be_hw_params(struct snd_pcm_substream *substream, static int avs_dai_hda_be_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct avs_dma_data *data; - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct hdac_ext_stream *link_stream; struct hdac_ext_link *link; struct hda_codec *codec; @@ -320,7 +320,7 @@ static int avs_dai_hda_be_hw_free(struct snd_pcm_substream *substream, struct sn data->path = NULL; /* clear link <-> stream mapping */ - codec = dev_to_hda_codec(asoc_rtd_to_codec(rtd, 0)->dev); + codec = dev_to_hda_codec(snd_soc_rtd_to_codec(rtd, 0)->dev); link = snd_hdac_ext_bus_get_hlink_by_addr(&codec->bus->core, codec->core.addr); if (!link) return -EINVAL; @@ -333,7 +333,7 @@ static int avs_dai_hda_be_hw_free(struct snd_pcm_substream *substream, struct sn static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct hdac_ext_stream *link_stream = runtime->private_data; struct hdac_ext_link *link; @@ -345,12 +345,11 @@ static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct sn if (link_stream->link_prepared) return 0; - codec = dev_to_hda_codec(asoc_rtd_to_codec(rtd, 0)->dev); + codec = dev_to_hda_codec(snd_soc_rtd_to_codec(rtd, 0)->dev); bus = &codec->bus->core; format_val = snd_hdac_calc_stream_format(runtime->rate, runtime->channels, runtime->format, runtime->sample_bits, 0); - snd_hdac_ext_stream_decouple(bus, link_stream, true); snd_hdac_ext_stream_reset(link_stream); snd_hdac_ext_stream_setup(link_stream, format_val); @@ -372,7 +371,7 @@ static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct sn static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct hdac_ext_stream *link_stream; struct avs_dma_data *data; int ret = 0; @@ -500,7 +499,7 @@ err: static void avs_dai_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct avs_dev *adev = to_avs_dev(dai->dev); struct avs_dma_data *data; @@ -534,7 +533,7 @@ static int avs_dai_fe_hw_params(struct snd_pcm_substream *substream, hdac_stream(host_stream)->period_bytes = 0; hdac_stream(host_stream)->format_val = 0; - fe = asoc_substream_to_rtd(substream); + fe = snd_soc_substream_to_rtd(substream); for_each_dpcm_be(fe, substream->stream, dpcm) { be = dpcm->be; be_hw_params = &be->dpcm[substream->stream].hw_params; @@ -604,7 +603,6 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so struct avs_dma_data *data; struct avs_dev *adev = to_avs_dev(dai->dev); struct hdac_ext_stream *host_stream; - struct hdac_bus *bus; unsigned int format_val; int ret; @@ -614,8 +612,6 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so if (hdac_stream(host_stream)->prepared) return 0; - bus = hdac_stream(host_stream)->bus; - snd_hdac_ext_stream_decouple(bus, data->host_stream, true); snd_hdac_stream_reset(hdac_stream(host_stream)); format_val = snd_hdac_calc_stream_format(runtime->rate, runtime->channels, runtime->format, @@ -625,7 +621,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so if (ret < 0) return ret; - ret = snd_hdac_stream_setup(hdac_stream(host_stream)); + ret = snd_hdac_ext_host_stream_setup(host_stream, false); if (ret < 0) return ret; @@ -639,7 +635,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct avs_dma_data *data; struct hdac_ext_stream *host_stream; struct hdac_bus *bus; @@ -869,7 +865,7 @@ static int avs_dai_resume_hw_params(struct snd_soc_dai *dai, struct avs_dma_data int ret; substream = data->substream; - rtd = asoc_substream_to_rtd(substream); + rtd = snd_soc_substream_to_rtd(substream); ret = dai->driver->ops->hw_params(substream, &rtd->dpcm[substream->stream].hw_params, dai); if (ret) @@ -964,7 +960,7 @@ static int avs_component_pm_op(struct snd_soc_component *component, bool be, for_each_component_dais(component, dai) { data = snd_soc_dai_dma_data_get_playback(dai); if (data) { - rtd = asoc_substream_to_rtd(data->substream); + rtd = snd_soc_substream_to_rtd(data->substream); if (rtd->dai_link->no_pcm == be && !rtd->dai_link->ignore_suspend) { ret = op(dai, data); if (ret < 0) { @@ -977,7 +973,7 @@ static int avs_component_pm_op(struct snd_soc_component *component, bool be, data = snd_soc_dai_dma_data_get_capture(dai); if (data) { - rtd = asoc_substream_to_rtd(data->substream); + rtd = snd_soc_substream_to_rtd(data->substream); if (rtd->dai_link->no_pcm == be && !rtd->dai_link->ignore_suspend) { ret = op(dai, data); if (ret < 0) { @@ -1081,7 +1077,7 @@ static const struct snd_pcm_hardware avs_pcm_hardware = { static int avs_component_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); /* only FE DAI links are handled here */ if (rtd->dai_link->no_pcm) @@ -1099,12 +1095,12 @@ static unsigned int avs_hda_stream_dpib_read(struct hdac_ext_stream *stream) static snd_pcm_uframes_t avs_component_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct avs_dma_data *data; struct hdac_ext_stream *host_stream; unsigned int pos; - data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); + data = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream); if (!data->host_stream) return 0; @@ -1129,7 +1125,7 @@ static int avs_component_mmap(struct snd_soc_component *component, static int avs_component_construct(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_pcm *pcm = rtd->pcm; if (dai->driver->playback.channels_min) @@ -1242,7 +1238,11 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l int i, j; ssp_count = adev->hw_cfg.i2s_caps.ctrl_count; - cpu_count = hweight_long(port_mask); + + cpu_count = 0; + for_each_set_bit(i, &port_mask, ssp_count) + if (!tdms || test_bit(0, &tdms[i])) + cpu_count++; if (tdms) for_each_set_bit(i, &port_mask, ssp_count) cpu_count += hweight_long(tdms[i]); @@ -1253,18 +1253,20 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l dai = cpus; for_each_set_bit(i, &port_mask, ssp_count) { - memcpy(dai, &i2s_dai_template, sizeof(*dai)); + if (!tdms || test_bit(0, &tdms[i])) { + memcpy(dai, &i2s_dai_template, sizeof(*dai)); - dai->name = - devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d Pin", i); - dai->playback.stream_name = - devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Tx", i); - dai->capture.stream_name = - devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Rx", i); + dai->name = + devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d Pin", i); + dai->playback.stream_name = + devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Tx", i); + dai->capture.stream_name = + devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Rx", i); - if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name) - return -ENOMEM; - dai++; + if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name) + return -ENOMEM; + dai++; + } } if (!tdms) @@ -1430,7 +1432,7 @@ static void avs_component_hda_remove(struct snd_soc_component *component) static int avs_component_hda_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct hdac_ext_stream *link_stream; struct hda_codec *codec; @@ -1464,7 +1466,7 @@ static int avs_component_hda_open(struct snd_soc_component *component, return snd_soc_set_runtime_hwparams(substream, &hwparams); } - codec = dev_to_hda_codec(asoc_rtd_to_codec(rtd, 0)->dev); + codec = dev_to_hda_codec(snd_soc_rtd_to_codec(rtd, 0)->dev); link_stream = snd_hdac_ext_stream_assign(&codec->bus->core, substream, HDAC_EXT_STREAM_TYPE_LINK); if (!link_stream) @@ -1477,7 +1479,7 @@ static int avs_component_hda_open(struct snd_soc_component *component, static int avs_component_hda_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct hdac_ext_stream *link_stream; /* only BE DAI links are handled here */ diff --git a/sound/soc/intel/avs/probes.c b/sound/soc/intel/avs/probes.c index 4cab8c6c45..bdc6b30dc0 100644 --- a/sound/soc/intel/avs/probes.c +++ b/sound/soc/intel/avs/probes.c @@ -145,7 +145,7 @@ static int avs_probe_compr_set_params(struct snd_compr_stream *cstream, ret = snd_hdac_stream_set_params(hdac_stream(host_stream), format_val); if (ret < 0) return ret; - ret = snd_hdac_stream_setup(hdac_stream(host_stream)); + ret = snd_hdac_stream_setup(hdac_stream(host_stream), false); if (ret < 0) return ret; diff --git a/sound/soc/intel/avs/registers.h b/sound/soc/intel/avs/registers.h index 2b464e466e..078a0ebafa 100644 --- a/sound/soc/intel/avs/registers.h +++ b/sound/soc/intel/avs/registers.h @@ -9,6 +9,8 @@ #ifndef __SOUND_SOC_INTEL_AVS_REGS_H #define __SOUND_SOC_INTEL_AVS_REGS_H +#include <linux/sizes.h> + #define AZX_PCIREG_PGCTL 0x44 #define AZX_PCIREG_CGCTL 0x48 #define AZX_PGCTL_LSRMD_MASK BIT(4) @@ -59,7 +61,7 @@ #define AVS_FW_REG_STATUS(adev) (AVS_FW_REG_BASE(adev) + 0x0) #define AVS_FW_REG_ERROR_CODE(adev) (AVS_FW_REG_BASE(adev) + 0x4) -#define AVS_WINDOW_CHUNK_SIZE PAGE_SIZE +#define AVS_WINDOW_CHUNK_SIZE SZ_4K #define AVS_FW_REGS_SIZE AVS_WINDOW_CHUNK_SIZE #define AVS_FW_REGS_WINDOW 0 /* DSP -> HOST communication window */ diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 45d0eb2a8e..41020409ff 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -15,6 +15,7 @@ #include "avs.h" #include "control.h" #include "topology.h" +#include "utils.h" /* Get pointer to vendor array at the specified offset. */ #define avs_tplg_vendor_array_at(array, offset) \ @@ -371,22 +372,50 @@ parse_audio_format_bitfield(struct snd_soc_component *comp, void *elem, void *ob return 0; } +static int avs_ssp_sprint(char *buf, size_t size, const char *fmt, int port, int tdm) +{ + char *needle = strstr(fmt, "%d"); + int retsize; + + /* + * If there is %d present in fmt string it should be replaced by either + * SSP or SSP:TDM, where SSP and TDM are numbers, all other formatting + * will be ignored. + */ + if (needle) { + retsize = scnprintf(buf, min_t(size_t, size, needle - fmt + 1), "%s", fmt); + retsize += scnprintf(buf + retsize, size - retsize, "%d", port); + if (tdm) + retsize += scnprintf(buf + retsize, size - retsize, ":%d", tdm); + retsize += scnprintf(buf + retsize, size - retsize, "%s", needle + 2); + return retsize; + } + + return snprintf(buf, size, "%s", fmt); +} + static int parse_link_formatted_string(struct snd_soc_component *comp, void *elem, void *object, u32 offset) { struct snd_soc_tplg_vendor_string_elem *tuple = elem; struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev); char *val = (char *)((u8 *)object + offset); + int ssp_port, tdm_slot; /* * Dynamic naming - string formats, e.g.: ssp%d - supported only for * topologies describing single device e.g.: an I2S codec on SSP0. */ - if (hweight_long(mach->mach_params.i2s_link_mask) != 1) + if (!avs_mach_singular_ssp(mach)) + return avs_parse_string_token(comp, elem, object, offset); + + ssp_port = avs_mach_ssp_port(mach); + if (!avs_mach_singular_tdm(mach, ssp_port)) return avs_parse_string_token(comp, elem, object, offset); - snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, tuple->string, - __ffs(mach->mach_params.i2s_link_mask)); + tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); + + avs_ssp_sprint(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, tuple->string, ssp_port, tdm_slot); return 0; } @@ -813,6 +842,7 @@ static void assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcfg_ext *cfg) { struct snd_soc_acpi_mach *mach; + int ssp_port, tdm_slot; if (!guid_equal(&cfg->type, &AVS_COPIER_MOD_UUID)) return; @@ -826,11 +856,22 @@ assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcf return; } + /* If topology sets value don't overwrite it */ + if (cfg->copier.vindex.val) + return; + mach = dev_get_platdata(comp->card->dev); - /* Automatic assignment only when board describes single SSP. */ - if (hweight_long(mach->mach_params.i2s_link_mask) == 1 && !cfg->copier.vindex.i2s.instance) - cfg->copier.vindex.i2s.instance = __ffs(mach->mach_params.i2s_link_mask); + if (!avs_mach_singular_ssp(mach)) + return; + ssp_port = avs_mach_ssp_port(mach); + + if (!avs_mach_singular_tdm(mach, ssp_port)) + return; + tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); + + cfg->copier.vindex.i2s.instance = ssp_port; + cfg->copier.vindex.i2s.time_slot = tdm_slot; } static int avs_tplg_parse_modcfg_ext(struct snd_soc_component *comp, @@ -1381,20 +1422,24 @@ static int avs_route_load(struct snd_soc_component *comp, int index, struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev); size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN; char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - u32 port; + int ssp_port, tdm_slot; /* See parse_link_formatted_string() for dynamic naming when(s). */ - if (hweight_long(mach->mach_params.i2s_link_mask) == 1) { - port = __ffs(mach->mach_params.i2s_link_mask); - - snprintf(buf, len, route->source, port); - strscpy((char *)route->source, buf, len); - snprintf(buf, len, route->sink, port); - strscpy((char *)route->sink, buf, len); - if (route->control) { - snprintf(buf, len, route->control, port); - strscpy((char *)route->control, buf, len); - } + if (!avs_mach_singular_ssp(mach)) + return 0; + ssp_port = avs_mach_ssp_port(mach); + + if (!avs_mach_singular_tdm(mach, ssp_port)) + return 0; + tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); + + avs_ssp_sprint(buf, len, route->source, ssp_port, tdm_slot); + strscpy((char *)route->source, buf, len); + avs_ssp_sprint(buf, len, route->sink, ssp_port, tdm_slot); + strscpy((char *)route->sink, buf, len); + if (route->control) { + avs_ssp_sprint(buf, len, route->control, ssp_port, tdm_slot); + strscpy((char *)route->control, buf, len); } return 0; @@ -1408,6 +1453,7 @@ static int avs_widget_load(struct snd_soc_component *comp, int index, struct avs_tplg_path_template *template; struct avs_soc_component *acomp = to_avs_soc_component(comp); struct avs_tplg *tplg; + int ssp_port, tdm_slot; if (!le32_to_cpu(dw->priv.size)) return 0; @@ -1419,16 +1465,28 @@ static int avs_widget_load(struct snd_soc_component *comp, int index, tplg = acomp->tplg; mach = dev_get_platdata(comp->card->dev); + if (!avs_mach_singular_ssp(mach)) + goto static_name; + ssp_port = avs_mach_ssp_port(mach); /* See parse_link_formatted_string() for dynamic naming when(s). */ - if (hweight_long(mach->mach_params.i2s_link_mask) == 1) { + 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; + char *buf; + + tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); + + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + avs_ssp_sprint(buf, size, dw->name, ssp_port, tdm_slot); kfree(w->name); /* w->name is freed later by soc_tplg_dapm_widget_create() */ - w->name = kasprintf(GFP_KERNEL, dw->name, __ffs(mach->mach_params.i2s_link_mask)); - if (!w->name) - return -ENOMEM; + w->name = buf; } +static_name: template = avs_tplg_path_template_create(comp, tplg, dw->priv.array, le32_to_cpu(dw->priv.size)); if (IS_ERR(template)) { diff --git a/sound/soc/intel/avs/utils.h b/sound/soc/intel/avs/utils.h new file mode 100644 index 0000000000..0b82a98ed0 --- /dev/null +++ b/sound/soc/intel/avs/utils.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Authors: Cezary Rojewski <cezary.rojewski@intel.com> + * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> + */ + +#ifndef __SOUND_SOC_INTEL_AVS_UTILS_H +#define __SOUND_SOC_INTEL_AVS_UTILS_H + +#include <sound/soc-acpi.h> + +static inline bool avs_mach_singular_ssp(struct snd_soc_acpi_mach *mach) +{ + return hweight_long(mach->mach_params.i2s_link_mask) == 1; +} + +static inline u32 avs_mach_ssp_port(struct snd_soc_acpi_mach *mach) +{ + return __ffs(mach->mach_params.i2s_link_mask); +} + +static inline bool avs_mach_singular_tdm(struct snd_soc_acpi_mach *mach, u32 port) +{ + unsigned long *tdms = mach->pdata; + + 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; + + return tdms ? __ffs(tdms[port]) : 0; +} + +static inline int avs_mach_get_ssp_tdm(struct device *dev, struct snd_soc_acpi_mach *mach, + int *ssp_port, int *tdm_slot) +{ + int port; + + if (!avs_mach_singular_ssp(mach)) { + dev_err(dev, "Invalid SSP configuration\n"); + return -EINVAL; + } + port = avs_mach_ssp_port(mach); + + if (!avs_mach_singular_tdm(mach, port)) { + dev_err(dev, "Invalid TDM configuration\n"); + return -EINVAL; + } + *ssp_port = port; + *tdm_slot = avs_mach_ssp_tdm(mach, *ssp_port); + + return 0; +} + +/* + * Macro to easily generate format strings + */ +#define AVS_STRING_FMT(prefix, suffix, ssp, tdm) \ + (tdm) ? prefix "%d:%d" suffix : prefix "%d" suffix, (ssp), (tdm) + +#endif |