aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2024-04-30 23:34:37 +0900
committerMark Brown <broonie@kernel.org>2024-04-30 23:34:37 +0900
commit34c43ad927da59d032e263ee3ae1528c1ed31780 (patch)
tree6f53a2044faa33a00d695e69905c676426b5c763
parent9a8cadddd9303ae15d1d518c4f2ddf00ee668729 (diff)
parentb831b4dca48dbe0f1f7705b44460dd9ca7f2f940 (diff)
downloadsound-34c43ad927da59d032e263ee3ae1528c1ed31780.tar.gz
ASoC: Intel: updates for 6.10 - part5
Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>: This patchset corrects a couple of mistakes corrected, improves snd_soc_card allocation. The new functionality is mostly for SoundWire platforms, with new SKUs for Dell and Acer, and support for the Cirrus Logic bridge/sidecar amplifier topology.
-rw-r--r--sound/soc/intel/boards/Kconfig1
-rw-r--r--sound/soc/intel/boards/Makefile1
-rw-r--r--sound/soc/intel/boards/bridge_cs35l56.c137
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_common.h1
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_generic.c50
-rw-r--r--sound/soc/intel/boards/sof_sdw.c106
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h27
-rw-r--r--sound/soc/intel/boards/sof_sdw_cs42l43.c14
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-lnl-match.c52
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c83
10 files changed, 397 insertions, 75 deletions
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 0ad7b0a1e237a..b122b8aedd9a9 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -690,6 +690,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
select SND_SOC_CS42L43_SDW
select MFD_CS42L43
select MFD_CS42L43_SDW
+ select SND_SOC_CS35L56_SPI
select SND_SOC_CS35L56_SDW
select SND_SOC_DMIC
select SND_SOC_INTEL_HDA_DSP_COMMON
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index 119413c262de7..1c099e717ecad 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -37,6 +37,7 @@ 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_maxim.o sof_sdw_rt_amp.o \
+ bridge_cs35l56.o \
sof_sdw_rt5682.o sof_sdw_rt700.o \
sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \
sof_sdw_rt712_sdca.o sof_sdw_rt722_sdca.o \
diff --git a/sound/soc/intel/boards/bridge_cs35l56.c b/sound/soc/intel/boards/bridge_cs35l56.c
new file mode 100644
index 0000000000000..c3995e724aed9
--- /dev/null
+++ b/sound/soc/intel/boards/bridge_cs35l56.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Intel SOF Machine Driver with Cirrus Logic CS35L56 Smart Amp
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include "sof_sdw_common.h"
+
+static const struct snd_soc_dapm_widget bridge_widgets[] = {
+ SND_SOC_DAPM_SPK("Bridge Speaker", NULL),
+};
+
+static const struct snd_soc_dapm_route bridge_map[] = {
+ {"Bridge Speaker", NULL, "AMPL SPK"},
+ {"Bridge Speaker", NULL, "AMPR SPK"},
+};
+
+static const char * const bridge_cs35l56_name_prefixes[] = {
+ "AMPL",
+ "AMPR",
+};
+
+static int bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ int i, ret;
+ unsigned int rx_mask = 3; // ASP RX1, RX2
+ unsigned int tx_mask = 3; // ASP TX1, TX2
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_dai *cpu_dai;
+
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s spk:cs35l56-bridge",
+ card->components);
+ if (!card->components)
+ return -ENOMEM;
+
+ ret = snd_soc_dapm_new_controls(&card->dapm, bridge_widgets,
+ ARRAY_SIZE(bridge_widgets));
+ if (ret) {
+ dev_err(card->dev, "widgets addition failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dapm_add_routes(&card->dapm, bridge_map, ARRAY_SIZE(bridge_map));
+ if (ret) {
+ dev_err(card->dev, "map addition failed: %d\n", ret);
+ return ret;
+ }
+
+ /* 4 x 16-bit sample slots and FSYNC=48000, BCLK=3.072 MHz */
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
+ ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_mask, rx_mask, 4, 16);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 3072000, SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+ }
+
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, rx_mask, 4, 16);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_pcm_stream bridge_params = {
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+};
+
+SND_SOC_DAILINK_DEFS(bridge_dai,
+ DAILINK_COMP_ARRAY(COMP_CODEC("cs42l43-codec", "cs42l43-asp")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("spi-cs35l56-left", "cs35l56-asp1"),
+ COMP_CODEC("spi-cs35l56-right", "cs35l56-asp1")),
+ DAILINK_COMP_ARRAY(COMP_PLATFORM("cs42l43-codec")));
+
+static const struct snd_soc_dai_link bridge_dai_template = {
+ .name = "cs42l43-cs35l56",
+ .init = bridge_cs35l56_asp_init,
+ .c2c_params = &bridge_params,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBC_CFC,
+ SND_SOC_DAILINK_REG(bridge_dai),
+};
+
+int bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
+ int *num_dais, int *num_devs)
+{
+ if (sof_sdw_quirk & SOF_SIDECAR_AMPS) {
+ (*num_dais)++;
+ (*num_devs) += ARRAY_SIZE(bridge_cs35l56_name_prefixes);
+ }
+
+ return 0;
+}
+
+int bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
+ struct snd_soc_dai_link **dai_links,
+ struct snd_soc_codec_conf **codec_conf)
+{
+ if (sof_sdw_quirk & SOF_SIDECAR_AMPS) {
+ **dai_links = bridge_dai_template;
+
+ for (int i = 0; i < ARRAY_SIZE(bridge_cs35l56_name_prefixes); i++) {
+ (*codec_conf)->dlc.name = (*dai_links)->codecs[i].name;
+ (*codec_conf)->name_prefix = bridge_cs35l56_name_prefixes[i];
+ (*codec_conf)++;
+ }
+
+ (*dai_links)++;
+ }
+
+ return 0;
+}
+
+int bridge_cs35l56_spk_init(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_links,
+ struct sof_sdw_codec_info *info,
+ bool playback)
+{
+ if (sof_sdw_quirk & SOF_SIDECAR_AMPS)
+ info->amp_num += ARRAY_SIZE(bridge_cs35l56_name_prefixes);
+
+ return 0;
+}
diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h
index 4b0b3959182e5..19b814dee4ad6 100644
--- a/sound/soc/intel/boards/skl_hda_dsp_common.h
+++ b/sound/soc/intel/boards/skl_hda_dsp_common.h
@@ -28,6 +28,7 @@ struct skl_hda_hdmi_pcm {
};
struct skl_hda_private {
+ struct snd_soc_card card;
struct list_head hdmi_pcm_list;
int pcm_count;
int dai_index;
diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c
index 4aa7fd2a05e46..88d91c0280bbb 100644
--- a/sound/soc/intel/boards/skl_hda_dsp_generic.c
+++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c
@@ -92,19 +92,6 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
return ret;
}
-static struct snd_soc_card hda_soc_card = {
- .name = "hda-dsp",
- .owner = THIS_MODULE,
- .dai_link = skl_hda_be_dai_links,
- .dapm_widgets = skl_hda_widgets,
- .dapm_routes = skl_hda_map,
- .add_dai_link = skl_hda_add_dai_link,
- .fully_routed = true,
- .late_probe = skl_hda_card_late_probe,
-};
-
-static char hda_soc_components[30];
-
#define IDISP_DAI_COUNT 3
#define HDAC_DAI_COUNT 2
#define DMIC_DAI_COUNT 2
@@ -115,9 +102,9 @@ static char hda_soc_components[30];
#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000
-static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params)
+static int skl_hda_fill_card_info(struct snd_soc_card *card,
+ struct snd_soc_acpi_mach_params *mach_params)
{
- struct snd_soc_card *card = &hda_soc_card;
struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_dai_link *dai_link;
u32 codec_count, codec_mask;
@@ -199,6 +186,7 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
{
struct snd_soc_acpi_mach *mach;
struct skl_hda_private *ctx;
+ struct snd_soc_card *card;
int ret;
dev_dbg(&pdev->dev, "entry\n");
@@ -213,32 +201,44 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
if (!mach)
return -EINVAL;
- snd_soc_card_set_drvdata(&hda_soc_card, ctx);
+ card = &ctx->card;
+ card->name = "hda-dsp",
+ card->owner = THIS_MODULE,
+ card->dai_link = skl_hda_be_dai_links,
+ card->dapm_widgets = skl_hda_widgets,
+ card->dapm_routes = skl_hda_map,
+ card->add_dai_link = skl_hda_add_dai_link,
+ card->fully_routed = true,
+ card->late_probe = skl_hda_card_late_probe,
+
+ snd_soc_card_set_drvdata(card, ctx);
- ret = skl_hda_fill_card_info(&mach->mach_params);
+ ret = skl_hda_fill_card_info(card, &mach->mach_params);
if (ret < 0) {
dev_err(&pdev->dev, "Unsupported HDAudio/iDisp configuration found\n");
return ret;
}
- ctx->pcm_count = hda_soc_card.num_links;
+ ctx->pcm_count = card->num_links;
ctx->dai_index = 1; /* hdmi codec dai name starts from index 1 */
ctx->platform_name = mach->mach_params.platform;
ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
- hda_soc_card.dev = &pdev->dev;
+ card->dev = &pdev->dev;
if (!snd_soc_acpi_sof_parent(&pdev->dev))
- hda_soc_card.disable_route_checks = true;
+ card->disable_route_checks = true;
if (mach->mach_params.dmic_num > 0) {
- snprintf(hda_soc_components, sizeof(hda_soc_components),
- "cfg-dmics:%d", mach->mach_params.dmic_num);
- hda_soc_card.components = hda_soc_components;
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "cfg-dmics:%d",
+ mach->mach_params.dmic_num);
+ if (!card->components)
+ return -ENOMEM;
}
- ret = devm_snd_soc_register_card(&pdev->dev, &hda_soc_card);
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
if (!ret)
- skl_set_hda_codec_autosuspend_delay(&hda_soc_card);
+ skl_set_hda_codec_autosuspend_delay(card);
return ret;
}
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index d65c5da49000a..b1595fdb500df 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -39,6 +39,8 @@ static void log_quirks(struct device *dev)
dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n");
if (sof_sdw_quirk & SOF_CODEC_SPKR)
dev_dbg(dev, "quirk SOF_CODEC_SPKR enabled\n");
+ if (sof_sdw_quirk & SOF_SIDECAR_AMPS)
+ dev_dbg(dev, "quirk SOF_SIDECAR_AMPS enabled\n");
}
static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
@@ -421,8 +423,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C0F")
},
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2 |
- SOF_SDW_FOUR_SPK),
+ RT711_JD2),
},
{
.callback = sof_sdw_quirk_cb,
@@ -996,6 +997,8 @@ static struct sof_sdw_codec_info codec_info_list[] = {
{
.part_id = 0x4243,
.codec_name = "cs42l43-codec",
+ .count_sidecar = bridge_cs35l56_count_sidecar,
+ .add_sidecar = bridge_cs35l56_add_sidecar,
.dais = {
{
.direction = {true, false},
@@ -1024,7 +1027,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
.init = sof_sdw_cs42l43_spk_init,
.rtd_init = cs42l43_spk_rtd_init,
- .quirk = SOF_CODEC_SPKR,
+ .quirk = SOF_CODEC_SPKR | SOF_SIDECAR_AMPS,
},
},
.dai_num = 4,
@@ -1280,6 +1283,8 @@ struct sof_sdw_endpoint {
u32 link_mask;
const char *codec_name;
+ const char *name_prefix;
+ bool include_sidecar;
struct sof_sdw_codec_info *codec_info;
const struct sof_sdw_dai_info *dai_info;
@@ -1335,17 +1340,18 @@ static struct sof_sdw_dailink *find_dailink(struct sof_sdw_dailink *dailinks,
static int parse_sdw_endpoints(struct snd_soc_card *card,
struct sof_sdw_dailink *sof_dais,
- struct sof_sdw_endpoint *sof_ends)
+ struct sof_sdw_endpoint *sof_ends,
+ int *num_devs)
{
struct device *dev = card->dev;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
- struct snd_soc_codec_conf *codec_conf = card->codec_conf;
const struct snd_soc_acpi_link_adr *adr_link;
struct sof_sdw_endpoint *sof_end = sof_ends;
int num_dais = 0;
int i, j;
+ int ret;
for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
int num_link_dailinks = 0;
@@ -1377,13 +1383,19 @@ static int parse_sdw_endpoints(struct snd_soc_card *card,
if (!codec_name)
return -ENOMEM;
- codec_conf->dlc.name = codec_name;
- codec_conf->name_prefix = adr_dev->name_prefix;
- codec_conf++;
-
dev_dbg(dev, "Adding prefix %s for %s\n",
adr_dev->name_prefix, codec_name);
+ sof_end->name_prefix = adr_dev->name_prefix;
+
+ if (codec_info->count_sidecar && codec_info->add_sidecar) {
+ ret = codec_info->count_sidecar(card, &num_dais, num_devs);
+ if (ret)
+ return ret;
+
+ sof_end->include_sidecar = true;
+ }
+
for (j = 0; j < adr_dev->num_endpoints; j++) {
const struct snd_soc_acpi_endpoint *adr_end;
const struct sof_sdw_dai_info *dai_info;
@@ -1444,20 +1456,33 @@ static int parse_sdw_endpoints(struct snd_soc_card *card,
ctx->append_dai_type |= (num_link_dailinks > 1);
}
- WARN_ON(codec_conf != card->codec_conf + card->num_configs);
-
return num_dais;
}
static int create_sdw_dailink(struct snd_soc_card *card,
struct sof_sdw_dailink *sof_dai,
struct snd_soc_dai_link **dai_links,
- int *be_id)
+ int *be_id, struct snd_soc_codec_conf **codec_conf)
{
struct device *dev = card->dev;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
struct sof_sdw_endpoint *sof_end;
int stream;
+ int ret;
+
+ list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
+ if (sof_end->name_prefix) {
+ (*codec_conf)->dlc.name = sof_end->codec_name;
+ (*codec_conf)->name_prefix = sof_end->name_prefix;
+ (*codec_conf)++;
+ }
+
+ if (sof_end->include_sidecar) {
+ ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf);
+ if (ret)
+ return ret;
+ }
+ }
for_each_pcm_streams(stream) {
static const char * const sdw_stream_name[] = {
@@ -1570,7 +1595,8 @@ static int create_sdw_dailink(struct snd_soc_card *card,
static int create_sdw_dailinks(struct snd_soc_card *card,
struct snd_soc_dai_link **dai_links, int *be_id,
- struct sof_sdw_dailink *sof_dais)
+ struct sof_sdw_dailink *sof_dais,
+ struct snd_soc_codec_conf **codec_conf)
{
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
int ret, i;
@@ -1582,7 +1608,8 @@ static int create_sdw_dailinks(struct snd_soc_card *card,
while (sof_dais->initialised) {
int current_be_id;
- ret = create_sdw_dailink(card, sof_dais, dai_links, &current_be_id);
+ ret = create_sdw_dailink(card, sof_dais, dai_links,
+ &current_be_id, codec_conf);
if (ret)
return ret;
@@ -1752,17 +1779,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
goto err_dai;
}
- /* will be populated when acpi endpoints are parsed */
- codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
- if (!codec_conf) {
- ret = -ENOMEM;
- goto err_end;
- }
-
- card->codec_conf = codec_conf;
- card->num_configs = num_devs;
-
- ret = parse_sdw_endpoints(card, sof_dais, sof_ends);
+ ret = parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs);
if (ret < 0)
goto err_end;
@@ -1799,6 +1816,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
sdw_be_num, ssp_num, dmic_num,
ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num);
+ codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
+ if (!codec_conf) {
+ ret = -ENOMEM;
+ goto err_end;
+ }
+
/* allocate BE dailinks */
num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num;
dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
@@ -1807,12 +1830,15 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
goto err_end;
}
+ card->codec_conf = codec_conf;
+ card->num_configs = num_devs;
card->dai_link = dai_links;
card->num_links = num_links;
/* SDW */
if (sdw_be_num) {
- ret = create_sdw_dailinks(card, &dai_links, &be_id, sof_dais);
+ ret = create_sdw_dailinks(card, &dai_links, &be_id,
+ sof_dais, &codec_conf);
if (ret)
goto err_end;
}
@@ -1848,6 +1874,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
goto err_end;
}
+ WARN_ON(codec_conf != card->codec_conf + card->num_configs);
WARN_ON(dai_links != card->dai_link + card->num_links);
err_end:
@@ -1879,15 +1906,6 @@ static int sof_sdw_card_late_probe(struct snd_soc_card *card)
return ret;
}
-/* SoC card */
-static const char sdw_card_long_name[] = "Intel Soundwire SOF";
-
-static struct snd_soc_card card_sof_sdw = {
- .name = "soundwire",
- .owner = THIS_MODULE,
- .late_probe = sof_sdw_card_late_probe,
-};
-
/* helper to get the link that the codec DAI is used */
static struct snd_soc_dai_link *mc_find_codec_dai_used(struct snd_soc_card *card,
const char *dai_name)
@@ -1939,20 +1957,24 @@ static void mc_dailink_exit_loop(struct snd_soc_card *card)
static int mc_probe(struct platform_device *pdev)
{
- struct snd_soc_card *card = &card_sof_sdw;
struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
+ struct snd_soc_card *card;
struct mc_private *ctx;
int amp_num = 0, i;
int ret;
- card->dev = &pdev->dev;
-
- dev_dbg(card->dev, "Entry\n");
+ dev_dbg(&pdev->dev, "Entry\n");
- ctx = devm_kzalloc(card->dev, sizeof(*ctx), GFP_KERNEL);
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
+ card = &ctx->card;
+ card->dev = &pdev->dev;
+ card->name = "soundwire",
+ card->owner = THIS_MODULE,
+ card->late_probe = sof_sdw_card_late_probe,
+
snd_soc_card_set_drvdata(card, ctx);
dmi_check_system(sof_sdw_quirk_table);
@@ -1988,7 +2010,7 @@ static int mc_probe(struct platform_device *pdev)
amp_num += codec_info_list[i].amp_num;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "cfg-amp:%d", amp_num);
+ " cfg-amp:%d", amp_num);
if (!card->components)
return -ENOMEM;
@@ -2001,8 +2023,6 @@ static int mc_probe(struct platform_device *pdev)
return -ENOMEM;
}
- card->long_name = sdw_card_long_name;
-
/* Register the card */
ret = devm_snd_soc_register_card(card->dev, card);
if (ret) {
diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h
index 89253938ebaaa..94657dd210f56 100644
--- a/sound/soc/intel/boards/sof_sdw_common.h
+++ b/sound/soc/intel/boards/sof_sdw_common.h
@@ -55,6 +55,16 @@ enum {
#define SOF_SDW_NO_AGGREGATION BIT(14)
/* If a CODEC has an optional speaker output, this quirk will enable it */
#define SOF_CODEC_SPKR BIT(15)
+/*
+ * If the CODEC has additional devices attached directly to it.
+ *
+ * For the cs42l43:
+ * - 0 - No speaker output
+ * - SOF_CODEC_SPKR - CODEC internal speaker
+ * - SOF_SIDECAR_AMPS - 2x Sidecar amplifiers + CODEC internal speaker
+ * - SOF_CODEC_SPKR | SOF_SIDECAR_AMPS - Not currently supported
+ */
+#define SOF_SIDECAR_AMPS BIT(16)
/* BT audio offload: reserve 3 bits for future */
#define SOF_BT_OFFLOAD_SSP_SHIFT 15
@@ -98,9 +108,16 @@ struct sof_sdw_codec_info {
const int dai_num;
int (*codec_card_late_probe)(struct snd_soc_card *card);
+
+ int (*count_sidecar)(struct snd_soc_card *card,
+ int *num_dais, int *num_devs);
+ int (*add_sidecar)(struct snd_soc_card *card,
+ struct snd_soc_dai_link **dai_links,
+ struct snd_soc_codec_conf **codec_conf);
};
struct mc_private {
+ struct snd_soc_card card;
struct snd_soc_jack sdw_headset;
struct sof_hdmi_private hdmi;
struct device *headset_codec_dev; /* only one headset per card */
@@ -170,6 +187,16 @@ int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card,
bool playback);
/* CS AMP support */
+int bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
+ int *num_dais, int *num_devs);
+int bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
+ struct snd_soc_dai_link **dai_links,
+ struct snd_soc_codec_conf **codec_conf);
+int bridge_cs35l56_spk_init(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_links,
+ struct sof_sdw_codec_info *info,
+ bool playback);
+
int sof_sdw_cs_amp_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
diff --git a/sound/soc/intel/boards/sof_sdw_cs42l43.c b/sound/soc/intel/boards/sof_sdw_cs42l43.c
index 5361249f0f536..0fd5e099bb1a7 100644
--- a/sound/soc/intel/boards/sof_sdw_cs42l43.c
+++ b/sound/soc/intel/boards/sof_sdw_cs42l43.c
@@ -124,10 +124,14 @@ int cs42l43_spk_rtd_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:cs42l43-spk",
- card->components);
- if (!card->components)
- return -ENOMEM;
+ if (!(sof_sdw_quirk & SOF_SIDECAR_AMPS)) {
+ /* Will be set by the bridge code in this case */
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s spk:cs42l43-spk",
+ card->components);
+ if (!card->components)
+ return -ENOMEM;
+ }
ret = snd_soc_dapm_new_controls(&card->dapm, cs42l43_spk_widgets,
ARRAY_SIZE(cs42l43_spk_widgets));
@@ -155,7 +159,7 @@ int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card,
info->amp_num++;
- return 0;
+ return bridge_cs35l56_spk_init(card, dai_links, info, playback);
}
int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
diff --git a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
index 74d6dcd7471f0..0318c1a46f3c6 100644
--- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
@@ -130,6 +130,33 @@ static const struct snd_soc_acpi_adr_device rt1316_3_group1_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = {
+ {
+ .adr = 0x000130025D131801ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "rt1318-1"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device rt1318_2_group1_adr[] = {
+ {
+ .adr = 0x000232025D131801ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "rt1318-2"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device rt714_0_adr[] = {
+ {
+ .adr = 0x000030025D071401ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt714"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt714_1_adr[] = {
{
.adr = 0x000130025D071401ull,
@@ -195,6 +222,25 @@ static const struct snd_soc_acpi_link_adr lnl_3_in_1_sdca[] = {
{}
};
+static const struct snd_soc_acpi_link_adr lnl_sdw_rt1318_l12_rt714_l0[] = {
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt1318_1_group1_adr),
+ .adr_d = rt1318_1_group1_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(rt1318_2_group1_adr),
+ .adr_d = rt1318_2_group1_adr,
+ },
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt714_0_adr),
+ .adr_d = rt714_0_adr,
+ },
+ {}
+};
+
/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = {
/* mockup tests need to be first */
@@ -240,6 +286,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-lnl-rt722-l0.tplg",
},
+ {
+ .link_mask = GENMASK(2, 0),
+ .links = lnl_sdw_rt1318_l12_rt714_l0,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-lnl-rt1318-l12-rt714-l0.tplg"
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_lnl_sdw_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index f95490a16b551..4eeec0bc92dc4 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -312,6 +312,15 @@ static const struct snd_soc_acpi_adr_device rt1316_3_single_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt1318_1_single_adr[] = {
+ {
+ .adr = 0x000130025D131801,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt1318"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = {
{
.adr = 0x000130025D131801ull,
@@ -348,7 +357,7 @@ static const struct snd_soc_acpi_adr_device rt714_1_adr[] = {
}
};
-static const struct snd_soc_acpi_link_adr mtl_712_only[] = {
+static const struct snd_soc_acpi_link_adr mtl_712_l0_1712_l3[] = {
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(rt712_0_single_adr),
@@ -362,6 +371,15 @@ static const struct snd_soc_acpi_link_adr mtl_712_only[] = {
{}
};
+static const struct snd_soc_acpi_link_adr mtl_712_l0[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt712_0_single_adr),
+ .adr_d = rt712_0_single_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
{ /* Jack Playback Endpoint */
.num = 0,
@@ -559,6 +577,49 @@ static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1316_l12_rt1713_l3[] =
{}
};
+static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1318_l1_rt1713_l3[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt713_0_single_adr),
+ .adr_d = rt713_0_single_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt1318_1_single_adr),
+ .adr_d = rt1318_1_single_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(rt1713_3_single_adr),
+ .adr_d = rt1713_3_single_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1318_l12_rt1713_l3[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt713_0_single_adr),
+ .adr_d = rt713_0_single_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt1318_1_group1_adr),
+ .adr_d = rt1318_1_group1_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(rt1318_2_group1_adr),
+ .adr_d = rt1318_2_group1_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(rt1713_3_single_adr),
+ .adr_d = rt1713_3_single_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1316_l12[] = {
{
.mask = BIT(0),
@@ -698,6 +759,18 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
.sof_tplg_filename = "sof-mtl-rt713-l0-rt1316-l12-rt1713-l3.tplg",
},
{
+ .link_mask = GENMASK(3, 0),
+ .links = mtl_rt713_l0_rt1318_l12_rt1713_l3,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-mtl-rt713-l0-rt1318-l12-rt1713-l3.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(1) | BIT(3),
+ .links = mtl_rt713_l0_rt1318_l1_rt1713_l3,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-mtl-rt713-l0-rt1318-l1-rt1713-l3.tplg",
+ },
+ {
.link_mask = GENMASK(2, 0),
.links = mtl_rt713_l0_rt1316_l12,
.drv_name = "sof_sdw",
@@ -705,11 +778,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
},
{
.link_mask = BIT(3) | BIT(0),
- .links = mtl_712_only,
+ .links = mtl_712_l0_1712_l3,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-mtl-rt712-l0-rt1712-l3.tplg",
},
{
+ .link_mask = BIT(0),
+ .links = mtl_712_l0,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-mtl-rt712-l0.tplg",
+ },
+ {
.link_mask = GENMASK(2, 0),
.links = mtl_sdw_rt1318_l12_rt714_l0,
.drv_name = "sof_sdw",