summaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/avs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel/avs')
-rw-r--r--sound/soc/intel/avs/avs.h38
-rw-r--r--sound/soc/intel/avs/board_selection.c11
-rw-r--r--sound/soc/intel/avs/boards/Kconfig10
-rw-r--r--sound/soc/intel/avs/boards/Makefile2
-rw-r--r--sound/soc/intel/avs/boards/da7219.c21
-rw-r--r--sound/soc/intel/avs/boards/es8336.c26
-rw-r--r--sound/soc/intel/avs/boards/i2s_test.c57
-rw-r--r--sound/soc/intel/avs/boards/max98357a.c18
-rw-r--r--sound/soc/intel/avs/boards/max98373.c20
-rw-r--r--sound/soc/intel/avs/boards/max98927.c20
-rw-r--r--sound/soc/intel/avs/boards/nau8825.c26
-rw-r--r--sound/soc/intel/avs/boards/rt274.c22
-rw-r--r--sound/soc/intel/avs/boards/rt286.c27
-rw-r--r--sound/soc/intel/avs/boards/rt298.c26
-rw-r--r--sound/soc/intel/avs/boards/rt5514.c187
-rw-r--r--sound/soc/intel/avs/boards/rt5663.c26
-rw-r--r--sound/soc/intel/avs/boards/rt5682.c26
-rw-r--r--sound/soc/intel/avs/boards/ssm4567.c22
-rw-r--r--sound/soc/intel/avs/cldma.h4
-rw-r--r--sound/soc/intel/avs/core.c21
-rw-r--r--sound/soc/intel/avs/debugfs.c4
-rw-r--r--sound/soc/intel/avs/ipc.c52
-rw-r--r--sound/soc/intel/avs/loader.c4
-rw-r--r--sound/soc/intel/avs/messages.c112
-rw-r--r--sound/soc/intel/avs/messages.h4
-rw-r--r--sound/soc/intel/avs/path.c31
-rw-r--r--sound/soc/intel/avs/pcm.c78
-rw-r--r--sound/soc/intel/avs/probes.c2
-rw-r--r--sound/soc/intel/avs/registers.h4
-rw-r--r--sound/soc/intel/avs/topology.c102
-rw-r--r--sound/soc/intel/avs/utils.h65
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