summaryrefslogtreecommitdiff
path: root/sound/soc/intel/boards
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel/boards')
-rw-r--r--sound/soc/intel/boards/Kconfig2
-rw-r--r--sound/soc/intel/boards/Makefile3
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c20
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c37
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c2
-rw-r--r--sound/soc/intel/boards/bytcr_wm5102.c2
-rw-r--r--sound/soc/intel/boards/sof_cs42l42.c3
-rw-r--r--sound/soc/intel/boards/sof_es8336.c16
-rw-r--r--sound/soc/intel/boards/sof_nau8825.c36
-rw-r--r--sound/soc/intel/boards/sof_realtek_common.c3
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c11
-rw-r--r--sound/soc/intel/boards/sof_sdw.c10
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h20
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1316.c239
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1318.c120
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt_amp.c (renamed from sound/soc/intel/boards/sof_sdw_rt1308.c)139
-rw-r--r--sound/soc/intel/boards/sof_ssp_amp.c5
17 files changed, 222 insertions, 446 deletions
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index a472de1909f4..99308ed85277 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -554,10 +554,12 @@ config SND_SOC_INTEL_SOF_NAU8825_MACH
select SND_SOC_RT1015P
select SND_SOC_MAX98373_I2C
select SND_SOC_MAX98357A
+ select SND_SOC_NAU8315
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_MAXIM_COMMON
+ select SND_SOC_INTEL_SOF_REALTEK_COMMON
help
This adds support for ASoC machine driver for SOF platforms
with nau8825 codec.
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index 7e1a4ff77ac3..d1fd7a2b32db 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -37,8 +37,7 @@ snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o
snd-soc-ehl-rt5660-objs := ehl_rt5660.o
snd-soc-sof-ssp-amp-objs := sof_ssp_amp.o
snd-soc-sof-sdw-objs += sof_sdw.o \
- sof_sdw_max98373.o sof_sdw_rt1308.o \
- sof_sdw_rt1316.o sof_sdw_rt1318.o \
+ sof_sdw_max98373.o sof_sdw_rt_amp.o \
sof_sdw_rt5682.o sof_sdw_rt700.o \
sof_sdw_rt711.o sof_sdw_rt711_sdca.o \
sof_sdw_rt715.o sof_sdw_rt715_sdca.o \
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index 09d1f0f6d686..df157b01df8b 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -497,21 +497,28 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
if (adev) {
snprintf(codec_name, sizeof(codec_name),
"i2c-%s", acpi_dev_name(adev));
- put_device(&adev->dev);
byt_cht_es8316_dais[dai_index].codecs->name = codec_name;
} else {
dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
return -ENXIO;
}
+ codec_dev = acpi_get_first_physical_node(adev);
+ acpi_dev_put(adev);
+ if (!codec_dev)
+ return -EPROBE_DEFER;
+ priv->codec_dev = get_device(codec_dev);
+
/* override platform name, if required */
byt_cht_es8316_card.dev = dev;
platform_name = mach->mach_params.platform;
ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_es8316_card,
platform_name);
- if (ret)
+ if (ret) {
+ put_device(codec_dev);
return ret;
+ }
/* Check for BYTCR or other platform and setup quirks */
dmi_id = dmi_first_match(byt_cht_es8316_quirk_table);
@@ -539,13 +546,10 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
/* get the clock */
priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
- if (IS_ERR(priv->mclk))
+ if (IS_ERR(priv->mclk)) {
+ put_device(codec_dev);
return dev_err_probe(dev, PTR_ERR(priv->mclk), "clk_get pmc_plt_clk_3 failed\n");
-
- codec_dev = acpi_get_first_physical_node(adev);
- if (!codec_dev)
- return -EPROBE_DEFER;
- priv->codec_dev = get_device(codec_dev);
+ }
if (quirk & BYT_CHT_ES8316_JD_INVERTED)
props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 6db07b2417ca..79e0039c79a3 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -571,6 +571,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_MCLK_EN),
},
{
+ /* Advantech MICA-071 */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"),
+ },
+ /* OVCD Th = 1500uA to reliable detect head-phones vs -set */
+ .driver_data = (void *)(BYT_RT5640_IN3_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_1500UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+ BYT_RT5640_MONO_SPEAKER |
+ BYT_RT5640_DIFF_MIC |
+ BYT_RT5640_MCLK_EN),
+ },
+ {
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 80 Cesium"),
@@ -796,6 +811,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
+ { /* HP Stream 8 */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 8 Tablet"),
+ },
+ .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
+ BYT_RT5640_JD_NOT_INV |
+ BYT_RT5640_SSP0_AIF1 |
+ BYT_RT5640_MCLK_EN),
+ },
{ /* I.T.Works TW891 */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
@@ -1611,13 +1636,18 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
if (adev) {
snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
"i2c-%s", acpi_dev_name(adev));
- put_device(&adev->dev);
byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;
} else {
dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
return -ENXIO;
}
+ codec_dev = acpi_get_first_physical_node(adev);
+ acpi_dev_put(adev);
+ if (!codec_dev)
+ return -EPROBE_DEFER;
+ priv->codec_dev = get_device(codec_dev);
+
/*
* swap SSP0 if bytcr is detected
* (will be overridden if DMI quirk is detected)
@@ -1692,11 +1722,6 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
byt_rt5640_quirk = quirk_override;
}
- codec_dev = acpi_get_first_physical_node(adev);
- if (!codec_dev)
- return -EPROBE_DEFER;
- priv->codec_dev = get_device(codec_dev);
-
if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
acpi_dev_add_driver_gpios(ACPI_COMPANION(priv->codec_dev),
byt_rt5640_hp_elitepad_1000g2_gpios);
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 81ac6eeda2e6..8fca9b82d4d0 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -922,7 +922,6 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
if (adev) {
snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name),
"i2c-%s", acpi_dev_name(adev));
- put_device(&adev->dev);
byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
} else {
dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
@@ -930,6 +929,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
}
codec_dev = acpi_get_first_physical_node(adev);
+ acpi_dev_put(adev);
if (!codec_dev)
return -EPROBE_DEFER;
priv->codec_dev = get_device(codec_dev);
diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c
index 1669eb3bd80f..c0706537f673 100644
--- a/sound/soc/intel/boards/bytcr_wm5102.c
+++ b/sound/soc/intel/boards/bytcr_wm5102.c
@@ -411,9 +411,9 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
return -ENOENT;
}
snprintf(codec_name, sizeof(codec_name), "spi-%s", acpi_dev_name(adev));
- put_device(&adev->dev);
codec_dev = bus_find_device_by_name(&spi_bus_type, NULL, codec_name);
+ acpi_dev_put(adev);
if (!codec_dev)
return -EPROBE_DEFER;
diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c
index e38bd2831e6a..e9d190cb13b0 100644
--- a/sound/soc/intel/boards/sof_cs42l42.c
+++ b/sound/soc/intel/boards/sof_cs42l42.c
@@ -336,6 +336,9 @@ static int create_spk_amp_dai_links(struct device *dev,
links[*id].platforms = platform_component;
links[*id].num_platforms = ARRAY_SIZE(platform_component);
links[*id].dpcm_playback = 1;
+ /* firmware-generated echo reference */
+ links[*id].dpcm_capture = 1;
+
links[*id].no_pcm = 1;
links[*id].cpus = &cpus[*id];
links[*id].num_cpus = 1;
diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index 70713e4b07dc..894b6610b9e2 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -681,7 +681,6 @@ static int sof_es8336_probe(struct platform_device *pdev)
if (adev) {
snprintf(codec_name, sizeof(codec_name),
"i2c-%s", acpi_dev_name(adev));
- put_device(&adev->dev);
dai_links[0].codecs->name = codec_name;
/* also fixup codec dai name if relevant */
@@ -692,16 +691,19 @@ static int sof_es8336_probe(struct platform_device *pdev)
return -ENXIO;
}
- ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card,
- mach->mach_params.platform);
- if (ret)
- return ret;
-
codec_dev = acpi_get_first_physical_node(adev);
+ acpi_dev_put(adev);
if (!codec_dev)
return -EPROBE_DEFER;
priv->codec_dev = get_device(codec_dev);
+ ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card,
+ mach->mach_params.platform);
+ if (ret) {
+ put_device(codec_dev);
+ return ret;
+ }
+
if (quirk & SOF_ES8336_JD_INVERTED)
props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
@@ -783,7 +785,7 @@ static int sof_es8336_remove(struct platform_device *pdev)
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
- cancel_delayed_work(&priv->pcm_pop_work);
+ cancel_delayed_work_sync(&priv->pcm_pop_work);
gpiod_put(priv->gpio_speakers);
device_remove_software_node(priv->codec_dev);
put_device(priv->codec_dev);
diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c
index 27880224359d..6794a0249a9a 100644
--- a/sound/soc/intel/boards/sof_nau8825.c
+++ b/sound/soc/intel/boards/sof_nau8825.c
@@ -48,6 +48,7 @@
#define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(15)
#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(16)
#define SOF_RT1015P_SPEAKER_AMP_PRESENT BIT(17)
+#define SOF_NAU8318_SPEAKER_AMP_PRESENT BIT(18)
static unsigned long sof_nau8825_quirk = SOF_NAU8825_SSP_CODEC(0);
@@ -338,6 +339,13 @@ static struct snd_soc_dai_link_component rt1019p_component[] = {
}
};
+static struct snd_soc_dai_link_component nau8318_components[] = {
+ {
+ .name = "NVTN2012:00",
+ .dai_name = "nau8315-hifi",
+ }
+};
+
static struct snd_soc_dai_link_component dummy_component[] = {
{
.name = "snd-soc-dummy",
@@ -479,13 +487,16 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].num_codecs = ARRAY_SIZE(max_98373_components);
links[id].init = max_98373_spk_codec_init;
links[id].ops = &max_98373_ops;
- /* feedback stream */
- links[id].dpcm_capture = 1;
} else if (sof_nau8825_quirk &
SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
max_98360a_dai_link(&links[id]);
} else if (sof_nau8825_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
sof_rt1015p_dai_link(&links[id]);
+ } else if (sof_nau8825_quirk &
+ SOF_NAU8318_SPEAKER_AMP_PRESENT) {
+ links[id].codecs = nau8318_components;
+ links[id].num_codecs = ARRAY_SIZE(nau8318_components);
+ links[id].init = speaker_codec_init;
} else {
goto devm_err;
}
@@ -493,6 +504,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].dpcm_playback = 1;
+ /* feedback stream or firmware-generated echo reference */
+ links[id].dpcm_capture = 1;
+
links[id].no_pcm = 1;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;
@@ -618,7 +632,7 @@ static const struct platform_device_id board_ids[] = {
},
{
- .name = "adl_rt1019p_nau8825",
+ .name = "adl_rt1019p_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1019P_SPEAKER_AMP_PRESENT |
@@ -626,7 +640,7 @@ static const struct platform_device_id board_ids[] = {
SOF_NAU8825_NUM_HDMIDEV(4)),
},
{
- .name = "adl_max98373_nau8825",
+ .name = "adl_max98373_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98373_SPEAKER_AMP_PRESENT |
@@ -637,7 +651,7 @@ static const struct platform_device_id board_ids[] = {
},
{
/* The limitation of length of char array, shorten the name */
- .name = "adl_mx98360a_nau8825",
+ .name = "adl_mx98360a_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
@@ -648,7 +662,7 @@ static const struct platform_device_id board_ids[] = {
},
{
- .name = "adl_rt1015p_nau8825",
+ .name = "adl_rt1015p_8825",
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1015P_SPEAKER_AMP_PRESENT |
@@ -657,6 +671,16 @@ static const struct platform_device_id board_ids[] = {
SOF_BT_OFFLOAD_SSP(2) |
SOF_SSP_BT_OFFLOAD_PRESENT),
},
+ {
+ .name = "adl_nau8318_8825",
+ .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
+ SOF_SPEAKER_AMP_PRESENT |
+ SOF_NAU8318_SPEAKER_AMP_PRESENT |
+ SOF_NAU8825_SSP_AMP(1) |
+ SOF_NAU8825_NUM_HDMIDEV(4) |
+ SOF_BT_OFFLOAD_SSP(2) |
+ SOF_SSP_BT_OFFLOAD_PRESENT),
+ },
{ }
};
MODULE_DEVICE_TABLE(platform, board_ids);
diff --git a/sound/soc/intel/boards/sof_realtek_common.c b/sound/soc/intel/boards/sof_realtek_common.c
index ff2851fc8930..6c12ca92f371 100644
--- a/sound/soc/intel/boards/sof_realtek_common.c
+++ b/sound/soc/intel/boards/sof_realtek_common.c
@@ -267,7 +267,8 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_soc_dai *codec_dai;
- int i, clk_freq, ret;
+ int i, clk_freq;
+ int ret = 0;
clk_freq = sof_dai_get_bclk(rtd);
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index 4a2f91249b10..71a11d747622 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -761,8 +761,6 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].num_codecs = ARRAY_SIZE(max_98373_components);
links[id].init = max_98373_spk_codec_init;
links[id].ops = &max_98373_ops;
- /* feedback stream */
- links[id].dpcm_capture = 1;
} else if (sof_rt5682_quirk &
SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
max_98360a_dai_link(&links[id]);
@@ -789,6 +787,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].dpcm_playback = 1;
+ /* feedback stream or firmware-generated echo reference */
+ links[id].dpcm_capture = 1;
+
links[id].no_pcm = 1;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;
@@ -1104,6 +1105,12 @@ static const struct platform_device_id board_ids[] = {
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4)),
},
+ {
+ .name = "jsl_rt5682",
+ .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
+ SOF_RT5682_MCLK_24MHZ |
+ SOF_RT5682_SSP_CODEC(0)),
+ },
{ }
};
MODULE_DEVICE_TABLE(platform, board_ids);
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index b58c7b35599d..d2ed807abde9 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -550,23 +550,23 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.direction = {true, false},
.dai_name = "rt1308-aif",
.ops = &sof_sdw_rt1308_i2s_ops,
- .init = sof_sdw_rt1308_init,
- .exit = sof_sdw_rt1308_exit,
+ .init = sof_sdw_rt_amp_init,
+ .exit = sof_sdw_rt_amp_exit,
.codec_type = SOF_SDW_CODEC_TYPE_AMP,
},
{
.part_id = 0x1316,
.direction = {true, true},
.dai_name = "rt1316-aif",
- .init = sof_sdw_rt1316_init,
- .exit = sof_sdw_rt1316_exit,
+ .init = sof_sdw_rt_amp_init,
+ .exit = sof_sdw_rt_amp_exit,
.codec_type = SOF_SDW_CODEC_TYPE_AMP,
},
{
.part_id = 0x1318,
.direction = {true, true},
.dai_name = "rt1318-aif",
- .init = sof_sdw_rt1318_init,
+ .init = sof_sdw_rt_amp_init,
.codec_type = SOF_SDW_CODEC_TYPE_AMP,
},
{
diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h
index 54a50f7da4da..350010b0e5f4 100644
--- a/sound/soc/intel/boards/sof_sdw_common.h
+++ b/sound/soc/intel/boards/sof_sdw_common.h
@@ -125,30 +125,18 @@ int sof_sdw_rt700_init(struct snd_soc_card *card,
struct sof_sdw_codec_info *info,
bool playback);
-/* RT1308 support */
+/* RT1308 I2S support */
extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops;
-int sof_sdw_rt1308_init(struct snd_soc_card *card,
+/* generic amp support */
+int sof_sdw_rt_amp_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
-int sof_sdw_rt1308_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
+int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
/* RT1316 support */
-int sof_sdw_rt1316_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-int sof_sdw_rt1316_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
-
-/* RT1318 support */
-int sof_sdw_rt1318_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
/* RT715 support */
int sof_sdw_rt715_init(struct snd_soc_card *card,
diff --git a/sound/soc/intel/boards/sof_sdw_rt1316.c b/sound/soc/intel/boards/sof_sdw_rt1316.c
deleted file mode 100644
index f6bbea0d3810..000000000000
--- a/sound/soc/intel/boards/sof_sdw_rt1316.c
+++ /dev/null
@@ -1,239 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-// Copyright (c) 2020 Intel Corporation
-
-/*
- * sof_sdw_rt1316 - Helpers to handle RT1316 from generic machine driver
- */
-
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <sound/control.h>
-#include <sound/soc.h>
-#include <sound/soc-acpi.h>
-#include <sound/soc-dapm.h>
-#include <linux/soundwire/sdw.h>
-#include <linux/soundwire/sdw_type.h>
-#include <linux/dmi.h>
-#include "sof_sdw_common.h"
-#include "sof_sdw_amp_coeff_tables.h"
-
-struct rt1316_platform_data {
- const unsigned char *bq_params;
- const unsigned int bq_params_cnt;
-};
-
-static const struct rt1316_platform_data dell_0b00_platform_data = {
- .bq_params = dell_0b00_bq_params,
- .bq_params_cnt = ARRAY_SIZE(dell_0b00_bq_params),
-};
-
-static const struct dmi_system_id dmi_platform_data[] = {
- /* AlderLake devices */
- {
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00")
- },
- .driver_data = (void *)&dell_0b00_platform_data,
- },
- {
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01")
- },
- .driver_data = (void *)&dell_0b00_platform_data,
- },
- {
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF")
- },
- .driver_data = (void *)&dell_0b00_platform_data,
- },
- {
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE")
- },
- .driver_data = (void *)&dell_0b00_platform_data,
- },
-};
-
-static int rt1316_add_device_props(struct device *sdw_dev)
-{
- struct property_entry props[3] = {};
- struct fwnode_handle *fwnode;
- const struct dmi_system_id *dmi_data;
- const struct rt1316_platform_data *pdata;
- unsigned char params[RT1316_MAX_BQ_REG];
- int ret;
-
- dmi_data = dmi_first_match(dmi_platform_data);
- if (!dmi_data)
- return 0;
-
- pdata = dmi_data->driver_data;
- memcpy(&params, pdata->bq_params, sizeof(unsigned char) * pdata->bq_params_cnt);
-
- props[0] = PROPERTY_ENTRY_U8_ARRAY("realtek,bq-params", params);
- props[1] = PROPERTY_ENTRY_U32("realtek,bq-params-cnt", pdata->bq_params_cnt);
-
- fwnode = fwnode_create_software_node(props, NULL);
- if (IS_ERR(fwnode))
- return PTR_ERR(fwnode);
-
- ret = device_add_software_node(sdw_dev, to_software_node(fwnode));
-
- fwnode_handle_put(fwnode);
-
- return ret;
-}
-
-static const struct snd_soc_dapm_widget rt1316_widgets[] = {
- SND_SOC_DAPM_SPK("Speaker", NULL),
-};
-
-/*
- * dapm routes for rt1316 will be registered dynamically according
- * to the number of rt1316 used. The first two entries will be registered
- * for one codec case, and the last two entries are also registered
- * if two 1316s are used.
- */
-static const struct snd_soc_dapm_route rt1316_map[] = {
- { "Speaker", NULL, "rt1316-1 SPOL" },
- { "Speaker", NULL, "rt1316-1 SPOR" },
- { "Speaker", NULL, "rt1316-2 SPOL" },
- { "Speaker", NULL, "rt1316-2 SPOR" },
-};
-
-static const struct snd_kcontrol_new rt1316_controls[] = {
- SOC_DAPM_PIN_SWITCH("Speaker"),
-};
-
-static int first_spk_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_card *card = rtd->card;
- int ret;
-
- card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "%s spk:rt1316",
- card->components);
- if (!card->components)
- return -ENOMEM;
-
- ret = snd_soc_add_card_controls(card, rt1316_controls,
- ARRAY_SIZE(rt1316_controls));
- if (ret) {
- dev_err(card->dev, "rt1316 controls addition failed: %d\n", ret);
- return ret;
- }
-
- ret = snd_soc_dapm_new_controls(&card->dapm, rt1316_widgets,
- ARRAY_SIZE(rt1316_widgets));
- if (ret) {
- dev_err(card->dev, "rt1316 widgets addition failed: %d\n", ret);
- return ret;
- }
-
- ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map, 2);
- if (ret)
- dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret);
-
- return ret;
-}
-
-static int second_spk_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_card *card = rtd->card;
- int ret;
-
- ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map + 2, 2);
- if (ret)
- dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret);
-
- return ret;
-}
-
-static int all_spk_init(struct snd_soc_pcm_runtime *rtd)
-{
- int ret;
-
- ret = first_spk_init(rtd);
- if (ret)
- return ret;
-
- return second_spk_init(rtd);
-}
-
-int sof_sdw_rt1316_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
-{
- struct mc_private *ctx = snd_soc_card_get_drvdata(card);
-
- if (ctx->amp_dev1) {
- device_remove_software_node(ctx->amp_dev1);
- put_device(ctx->amp_dev1);
- }
-
- if (ctx->amp_dev2) {
- device_remove_software_node(ctx->amp_dev2);
- put_device(ctx->amp_dev2);
- }
-
- return 0;
-}
-
-int sof_sdw_rt1316_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct device *sdw_dev1, *sdw_dev2;
- int ret;
-
- /* Count amp number and do init on playback link only. */
- if (!playback)
- return 0;
-
- info->amp_num++;
- if (info->amp_num == 1)
- dai_links->init = first_spk_init;
-
- if (info->amp_num == 2) {
- sdw_dev1 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name);
- if (!sdw_dev1)
- return -EPROBE_DEFER;
-
- ret = rt1316_add_device_props(sdw_dev1);
- if (ret < 0) {
- put_device(sdw_dev1);
- return ret;
- }
- ctx->amp_dev1 = sdw_dev1;
-
- sdw_dev2 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[1].name);
- if (!sdw_dev2)
- return -EPROBE_DEFER;
-
- ret = rt1316_add_device_props(sdw_dev2);
- if (ret < 0) {
- put_device(sdw_dev2);
- return ret;
- }
- ctx->amp_dev2 = sdw_dev2;
-
- /*
- * if two 1316s are in one dai link, the init function
- * in this dai link will be first set for the first speaker,
- * and it should be reset to initialize all speakers when
- * the second speaker is found.
- */
- if (dai_links->init)
- dai_links->init = all_spk_init;
- else
- dai_links->init = second_spk_init;
- }
-
- return 0;
-}
diff --git a/sound/soc/intel/boards/sof_sdw_rt1318.c b/sound/soc/intel/boards/sof_sdw_rt1318.c
deleted file mode 100644
index dbee4bf5c814..000000000000
--- a/sound/soc/intel/boards/sof_sdw_rt1318.c
+++ /dev/null
@@ -1,120 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-// Copyright (c) 2022 Intel Corporation
-
-/*
- * sof_sdw_rt1318 - Helpers to handle RT1318 from generic machine driver
- */
-
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <sound/control.h>
-#include <sound/soc.h>
-#include <sound/soc-acpi.h>
-#include <sound/soc-dapm.h>
-#include "sof_sdw_common.h"
-
-static const struct snd_soc_dapm_widget rt1318_widgets[] = {
- SND_SOC_DAPM_SPK("Speaker", NULL),
-};
-
-/*
- * dapm routes for rt1318 will be registered dynamically according
- * to the number of rt1318 used. The first two entries will be registered
- * for one codec case, and the last two entries are also registered
- * if two 1318s are used.
- */
-static const struct snd_soc_dapm_route rt1318_map[] = {
- { "Speaker", NULL, "rt1318-1 SPOL" },
- { "Speaker", NULL, "rt1318-1 SPOR" },
- { "Speaker", NULL, "rt1318-2 SPOL" },
- { "Speaker", NULL, "rt1318-2 SPOR" },
-};
-
-static const struct snd_kcontrol_new rt1318_controls[] = {
- SOC_DAPM_PIN_SWITCH("Speaker"),
-};
-
-static int first_spk_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_card *card = rtd->card;
- int ret;
-
- card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "%s spk:rt1318",
- card->components);
- if (!card->components)
- return -ENOMEM;
-
- ret = snd_soc_add_card_controls(card, rt1318_controls,
- ARRAY_SIZE(rt1318_controls));
- if (ret) {
- dev_err(card->dev, "rt1318 controls addition failed: %d\n", ret);
- return ret;
- }
-
- ret = snd_soc_dapm_new_controls(&card->dapm, rt1318_widgets,
- ARRAY_SIZE(rt1318_widgets));
- if (ret) {
- dev_err(card->dev, "rt1318 widgets addition failed: %d\n", ret);
- return ret;
- }
-
- ret = snd_soc_dapm_add_routes(&card->dapm, rt1318_map, 2);
- if (ret)
- dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret);
-
- return ret;
-}
-
-static int second_spk_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_card *card = rtd->card;
- int ret;
-
- ret = snd_soc_dapm_add_routes(&card->dapm, rt1318_map + 2, 2);
- if (ret)
- dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret);
-
- return ret;
-}
-
-static int all_spk_init(struct snd_soc_pcm_runtime *rtd)
-{
- int ret;
-
- ret = first_spk_init(rtd);
- if (ret)
- return ret;
-
- return second_spk_init(rtd);
-}
-
-int sof_sdw_rt1318_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- /* Count amp number and do init on playback link only. */
- if (!playback)
- return 0;
-
- info->amp_num++;
- if (info->amp_num == 1)
- dai_links->init = first_spk_init;
-
- if (info->amp_num == 2) {
- /*
- * if two 1318s are in one dai link, the init function
- * in this dai link will be first set for the first speaker,
- * and it should be reset to initialize all speakers when
- * the second speaker is found.
- */
- if (dai_links->init)
- dai_links->init = all_spk_init;
- else
- dai_links->init = second_spk_init;
- }
-
- return 0;
-}
diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt_amp.c
index a19b055b9c6f..26bf9e0dd3d2 100644
--- a/sound/soc/intel/boards/sof_sdw_rt1308.c
+++ b/sound/soc/intel/boards/sof_sdw_rt_amp.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
-// Copyright (c) 2020 Intel Corporation
+// Copyright (c) 2022 Intel Corporation
/*
- * sof_sdw_rt1308 - Helpers to handle RT1308 from generic machine driver
+ * sof_sdw_rt_amp - Helpers to handle RT1308/RT1316/RT1318 from generic machine driver
*/
#include <linux/device.h>
@@ -18,16 +18,26 @@
#include "sof_sdw_amp_coeff_tables.h"
#include "../../codecs/rt1308.h"
-struct rt1308_platform_data {
+#define CODEC_NAME_SIZE 7
+
+/* choose a larger value to resolve compatibility issues */
+#define RT_AMP_MAX_BQ_REG RT1316_MAX_BQ_REG
+
+struct rt_amp_platform_data {
const unsigned char *bq_params;
const unsigned int bq_params_cnt;
};
-static const struct rt1308_platform_data dell_0a5d_platform_data = {
+static const struct rt_amp_platform_data dell_0a5d_platform_data = {
.bq_params = dell_0a5d_bq_params,
.bq_params_cnt = ARRAY_SIZE(dell_0a5d_bq_params),
};
+static const struct rt_amp_platform_data dell_0b00_platform_data = {
+ .bq_params = dell_0b00_bq_params,
+ .bq_params_cnt = ARRAY_SIZE(dell_0b00_bq_params),
+};
+
static const struct dmi_system_id dmi_platform_data[] = {
/* CometLake devices */
{
@@ -59,15 +69,45 @@ static const struct dmi_system_id dmi_platform_data[] = {
},
.driver_data = (void *)&dell_0a5d_platform_data,
},
+ /* AlderLake devices */
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00")
+ },
+ .driver_data = (void *)&dell_0b00_platform_data,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01")
+ },
+ .driver_data = (void *)&dell_0b00_platform_data,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF")
+ },
+ .driver_data = (void *)&dell_0b00_platform_data,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE")
+ },
+ .driver_data = (void *)&dell_0b00_platform_data,
+ },
+ {},
};
-static int rt1308_add_device_props(struct device *sdw_dev)
+static int rt_amp_add_device_props(struct device *sdw_dev)
{
struct property_entry props[3] = {};
struct fwnode_handle *fwnode;
const struct dmi_system_id *dmi_data;
- const struct rt1308_platform_data *pdata;
- unsigned char params[RT1308_MAX_BQ_REG];
+ const struct rt_amp_platform_data *pdata;
+ unsigned char params[RT_AMP_MAX_BQ_REG];
int ret;
dmi_data = dmi_first_match(dmi_platform_data);
@@ -91,15 +131,19 @@ static int rt1308_add_device_props(struct device *sdw_dev)
return ret;
}
-static const struct snd_soc_dapm_widget rt1308_widgets[] = {
+static const struct snd_kcontrol_new rt_amp_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Speaker"),
+};
+
+static const struct snd_soc_dapm_widget rt_amp_widgets[] = {
SND_SOC_DAPM_SPK("Speaker", NULL),
};
/*
- * dapm routes for rt1308 will be registered dynamically according
- * to the number of rt1308 used. The first two entries will be registered
- * for one codec case, and the last two entries are also registered
- * if two 1308s are used.
+ * dapm routes for rt1308/rt1316/rt1318 will be registered dynamically
+ * according to the number of rt1308/rt1316/rt1318 used. The first two
+ * entries will be registered for one codec case, and the last two entries
+ * are also registered if two 1308s/1316s/1318s are used.
*/
static const struct snd_soc_dapm_route rt1308_map[] = {
{ "Speaker", NULL, "rt1308-1 SPOL" },
@@ -108,36 +152,69 @@ static const struct snd_soc_dapm_route rt1308_map[] = {
{ "Speaker", NULL, "rt1308-2 SPOR" },
};
-static const struct snd_kcontrol_new rt1308_controls[] = {
- SOC_DAPM_PIN_SWITCH("Speaker"),
+static const struct snd_soc_dapm_route rt1316_map[] = {
+ { "Speaker", NULL, "rt1316-1 SPOL" },
+ { "Speaker", NULL, "rt1316-1 SPOR" },
+ { "Speaker", NULL, "rt1316-2 SPOL" },
+ { "Speaker", NULL, "rt1316-2 SPOR" },
};
+static const struct snd_soc_dapm_route rt1318_map[] = {
+ { "Speaker", NULL, "rt1318-1 SPOL" },
+ { "Speaker", NULL, "rt1318-1 SPOR" },
+ { "Speaker", NULL, "rt1318-2 SPOL" },
+ { "Speaker", NULL, "rt1318-2 SPOR" },
+};
+
+static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_pcm_runtime *rtd,
+ char *codec_name)
+{
+ const char *dai_name;
+
+ dai_name = rtd->dai_link->codecs->dai_name;
+
+ /* get the codec name */
+ snprintf(codec_name, CODEC_NAME_SIZE, "%s", dai_name);
+
+ /* choose the right codec's map */
+ if (strcmp(codec_name, "rt1308") == 0)
+ return rt1308_map;
+ else if (strcmp(codec_name, "rt1316") == 0)
+ return rt1316_map;
+ else
+ return rt1318_map;
+}
+
static int first_spk_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
+ const struct snd_soc_dapm_route *rt_amp_map;
+ char codec_name[CODEC_NAME_SIZE];
int ret;
+ rt_amp_map = get_codec_name_and_route(rtd, codec_name);
+
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "%s spk:rt1308",
- card->components);
+ "%s spk:%s",
+ card->components, codec_name);
if (!card->components)
return -ENOMEM;
- ret = snd_soc_add_card_controls(card, rt1308_controls,
- ARRAY_SIZE(rt1308_controls));
+ ret = snd_soc_add_card_controls(card, rt_amp_controls,
+ ARRAY_SIZE(rt_amp_controls));
if (ret) {
- dev_err(card->dev, "rt1308 controls addition failed: %d\n", ret);
+ dev_err(card->dev, "%s controls addition failed: %d\n", codec_name, ret);
return ret;
}
- ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_widgets,
- ARRAY_SIZE(rt1308_widgets));
+ ret = snd_soc_dapm_new_controls(&card->dapm, rt_amp_widgets,
+ ARRAY_SIZE(rt_amp_widgets));
if (ret) {
- dev_err(card->dev, "rt1308 widgets addition failed: %d\n", ret);
+ dev_err(card->dev, "%s widgets addition failed: %d\n", codec_name, ret);
return ret;
}
- ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_map, 2);
+ ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map, 2);
if (ret)
dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret);
@@ -147,9 +224,13 @@ static int first_spk_init(struct snd_soc_pcm_runtime *rtd)
static int second_spk_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
+ const struct snd_soc_dapm_route *rt_amp_map;
+ char codec_name[CODEC_NAME_SIZE];
int ret;
- ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_map + 2, 2);
+ rt_amp_map = get_codec_name_and_route(rtd, codec_name);
+
+ ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map + 2, 2);
if (ret)
dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret);
@@ -204,7 +285,7 @@ struct snd_soc_ops sof_sdw_rt1308_i2s_ops = {
.hw_params = rt1308_i2s_hw_params,
};
-int sof_sdw_rt1308_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
+int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
{
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
@@ -221,7 +302,7 @@ int sof_sdw_rt1308_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_
return 0;
}
-int sof_sdw_rt1308_init(struct snd_soc_card *card,
+int sof_sdw_rt_amp_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
@@ -244,7 +325,7 @@ int sof_sdw_rt1308_init(struct snd_soc_card *card,
if (!sdw_dev1)
return -EPROBE_DEFER;
- ret = rt1308_add_device_props(sdw_dev1);
+ ret = rt_amp_add_device_props(sdw_dev1);
if (ret < 0) {
put_device(sdw_dev1);
return ret;
@@ -255,7 +336,7 @@ int sof_sdw_rt1308_init(struct snd_soc_card *card,
if (!sdw_dev2)
return -EPROBE_DEFER;
- ret = rt1308_add_device_props(sdw_dev2);
+ ret = rt_amp_add_device_props(sdw_dev2);
if (ret < 0) {
put_device(sdw_dev2);
return ret;
@@ -263,7 +344,7 @@ int sof_sdw_rt1308_init(struct snd_soc_card *card,
ctx->amp_dev2 = sdw_dev2;
/*
- * if two 1308s are in one dai link, the init function
+ * if two amps are in one dai link, the init function
* in this dai link will be first set for the first speaker,
* and it should be reset to initialize all speakers when
* the second speaker is found.
diff --git a/sound/soc/intel/boards/sof_ssp_amp.c b/sound/soc/intel/boards/sof_ssp_amp.c
index 94d25aeb6e7c..7b74f122e340 100644
--- a/sound/soc/intel/boards/sof_ssp_amp.c
+++ b/sound/soc/intel/boards/sof_ssp_amp.c
@@ -258,13 +258,12 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
sof_rt1308_dai_link(&links[id]);
} else if (sof_ssp_amp_quirk & SOF_CS35L41_SPEAKER_AMP_PRESENT) {
cs35l41_set_dai_link(&links[id]);
-
- /* feedback from amplifier */
- links[id].dpcm_capture = 1;
}
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].dpcm_playback = 1;
+ /* feedback from amplifier or firmware-generated echo reference */
+ links[id].dpcm_capture = 1;
links[id].no_pcm = 1;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;