aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc-acpi.h2
-rw-r--r--sound/soc/intel/boards/Kconfig2
-rw-r--r--sound/soc/intel/boards/bytcht_cx2072x.c4
-rw-r--r--sound/soc/intel/boards/bytcht_da7213.c4
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c2
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c2
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c2
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c4
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c4
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_common.c60
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_common.h39
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_generic.c58
-rw-r--r--sound/soc/intel/boards/sof_es8336.c12
-rw-r--r--sound/soc/intel/boards/sof_sdw.c85
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h2
-rw-r--r--sound/soc/intel/boards/sof_wm8804.c4
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-adl-match.c105
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-arl-match.c244
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-hda-match.c12
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-lnl-match.c104
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt_amp.c11
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c19
-rw-r--r--sound/soc/sof/intel/hda.c281
23 files changed, 782 insertions, 280 deletions
diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h
index b6d301946244..c1552bc6e31c 100644
--- a/include/sound/soc-acpi.h
+++ b/include/sound/soc-acpi.h
@@ -73,6 +73,7 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
* @subsystem_rev: optional PCI SSID revision value
* @subsystem_id_set: true if a value has been written to
* subsystem_vendor and subsystem_device.
+ * @bt_link_mask: BT offload link enabled on the board
*/
struct snd_soc_acpi_mach_params {
u32 acpi_ipc_irq_index;
@@ -89,6 +90,7 @@ struct snd_soc_acpi_mach_params {
unsigned short subsystem_device;
unsigned short subsystem_rev;
bool subsystem_id_set;
+ u32 bt_link_mask;
};
/**
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index cb952183f5ed..793a9170513a 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -305,7 +305,6 @@ if SND_SOC_SOF_HDA_AUDIO_CODEC
config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH
tristate "Skylake+ with HDA Codecs"
depends on SND_HDA_CODEC_HDMI
- select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_DMIC
# SND_SOC_HDAC_HDA is already selected
@@ -524,6 +523,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
select SND_SOC_RT1308
select SND_SOC_RT1316_SDW
select SND_SOC_RT1318_SDW
+ select SND_SOC_RT1320_SDW
select SND_SOC_RT5682_SDW
select SND_SOC_CS42L42_SDW
select SND_SOC_CS42L43
diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c
index df3c2a7b64d2..8c2b4ab764bb 100644
--- a/sound/soc/intel/boards/bytcht_cx2072x.c
+++ b/sound/soc/intel/boards/bytcht_cx2072x.c
@@ -255,7 +255,11 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev)
snprintf(codec_name, sizeof(codec_name), "i2c-%s",
acpi_dev_name(adev));
byt_cht_cx2072x_dais[dai_index].codecs->name = codec_name;
+ } else {
+ dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+ return -ENOENT;
}
+
acpi_dev_put(adev);
/* override platform name, if required */
diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c
index 08c598b7e1ee..9178bbe8d995 100644
--- a/sound/soc/intel/boards/bytcht_da7213.c
+++ b/sound/soc/intel/boards/bytcht_da7213.c
@@ -258,7 +258,11 @@ static int bytcht_da7213_probe(struct platform_device *pdev)
snprintf(codec_name, sizeof(codec_name),
"i2c-%s", acpi_dev_name(adev));
dailink[dai_index].codecs->name = codec_name;
+ } else {
+ dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+ return -ENOENT;
}
+
acpi_dev_put(adev);
/* override platform name, if required */
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index 77b91ea4dc32..3539c9ff0fd2 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -562,7 +562,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
byt_cht_es8316_dais[dai_index].codecs->name = codec_name;
} else {
dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
- return -ENXIO;
+ return -ENOENT;
}
codec_dev = acpi_get_first_physical_node(adev);
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index db4a33680d94..4479825c08b5 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -1693,7 +1693,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
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;
+ return -ENOENT;
}
codec_dev = acpi_get_first_physical_node(adev);
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 8514b79f389b..1f54da98aacf 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -926,7 +926,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
} else {
dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
- return -ENXIO;
+ return -ENOENT;
}
codec_dev = acpi_get_first_physical_node(adev);
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c
index 1da9ceee4d59..ac23a8b7cafc 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5645.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
@@ -582,7 +582,11 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
snprintf(cht_rt5645_codec_name, sizeof(cht_rt5645_codec_name),
"i2c-%s", acpi_dev_name(adev));
cht_dailink[dai_index].codecs->name = cht_rt5645_codec_name;
+ } else {
+ dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+ return -ENOENT;
}
+
/* acpi_get_first_physical_node() returns a borrowed ref, no need to deref */
codec_dev = acpi_get_first_physical_node(adev);
acpi_dev_put(adev);
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c
index d68e5bc755de..c6c469d51243 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5672.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5672.c
@@ -479,7 +479,11 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
snprintf(drv->codec_name, sizeof(drv->codec_name),
"i2c-%s", acpi_dev_name(adev));
cht_dailink[dai_index].codecs->name = drv->codec_name;
+ } else {
+ dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+ return -ENOENT;
}
+
acpi_dev_put(adev);
/* Use SSP0 on Bay Trail CR devices */
diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.c b/sound/soc/intel/boards/skl_hda_dsp_common.c
index e9cefa4ae56d..5019bdfa5b45 100644
--- a/sound/soc/intel/boards/skl_hda_dsp_common.c
+++ b/sound/soc/intel/boards/skl_hda_dsp_common.c
@@ -11,7 +11,6 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
-#include "../../codecs/hdac_hdmi.h"
#include "skl_hda_dsp_common.h"
#include <sound/hda_codec.h>
@@ -22,21 +21,16 @@
int skl_hda_hdmi_add_pcm(struct snd_soc_card *card, int device)
{
struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
- struct skl_hda_hdmi_pcm *pcm;
+ struct snd_soc_dai *dai;
char dai_name[NAME_SIZE];
- pcm = devm_kzalloc(card->dev, sizeof(*pcm), GFP_KERNEL);
- if (!pcm)
- return -ENOMEM;
-
snprintf(dai_name, sizeof(dai_name), "intel-hdmi-hifi%d",
ctx->dai_index);
- pcm->codec_dai = snd_soc_card_get_codec_dai(card, dai_name);
- if (!pcm->codec_dai)
+ dai = snd_soc_card_get_codec_dai(card, dai_name);
+ if (!dai)
return -EINVAL;
- pcm->device = device;
- list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
+ ctx->hdmi.hdmi_comp = dai->component;
return 0;
}
@@ -75,6 +69,11 @@ SND_SOC_DAILINK_DEF(dmic_codec,
SND_SOC_DAILINK_DEF(dmic16k,
DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
+SND_SOC_DAILINK_DEF(bt_offload_pin,
+ DAILINK_COMP_ARRAY(COMP_CPU(""))); /* initialized in driver probe function */
+SND_SOC_DAILINK_DEF(dummy,
+ DAILINK_COMP_ARRAY(COMP_DUMMY()));
+
SND_SOC_DAILINK_DEF(platform,
DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
@@ -132,37 +131,26 @@ struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS] = {
.no_pcm = 1,
SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform),
},
+ {
+ .name = NULL, /* initialized in driver probe function */
+ .id = 8,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .no_pcm = 1,
+ SND_SOC_DAILINK_REG(bt_offload_pin, dummy, platform),
+ },
};
int skl_hda_hdmi_jack_init(struct snd_soc_card *card)
{
struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
- struct snd_soc_component *component = NULL;
- struct skl_hda_hdmi_pcm *pcm;
- char jack_name[NAME_SIZE];
- int err;
-
- if (ctx->common_hdmi_codec_drv)
- return skl_hda_hdmi_build_controls(card);
-
- list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
- component = pcm->codec_dai->component;
- snprintf(jack_name, sizeof(jack_name),
- "HDMI/DP, pcm=%d Jack", pcm->device);
- err = snd_soc_card_jack_new(card, jack_name,
- SND_JACK_AVOUT, &pcm->hdmi_jack);
-
- if (err)
- return err;
-
- err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
- &pcm->hdmi_jack);
- if (err < 0)
- return err;
- }
-
- if (!component)
+
+ /* HDMI disabled, do not create controls */
+ if (!ctx->hdmi.idisp_codec)
+ return 0;
+
+ if (!ctx->hdmi.hdmi_comp)
return -EINVAL;
- return hdac_hdmi_jack_port_init(component, &card->dapm);
+ return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp);
}
diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h
index 19b814dee4ad..40ffbccb2fe0 100644
--- a/sound/soc/intel/boards/skl_hda_dsp_common.h
+++ b/sound/soc/intel/boards/skl_hda_dsp_common.h
@@ -17,51 +17,22 @@
#include <sound/hda_codec.h>
#include "../../codecs/hdac_hda.h"
#include "hda_dsp_common.h"
+#include "sof_hdmi_common.h"
-#define HDA_DSP_MAX_BE_DAI_LINKS 7
-
-struct skl_hda_hdmi_pcm {
- struct list_head head;
- struct snd_soc_dai *codec_dai;
- struct snd_soc_jack hdmi_jack;
- int device;
-};
+#define HDA_DSP_MAX_BE_DAI_LINKS 8
struct skl_hda_private {
struct snd_soc_card card;
- struct list_head hdmi_pcm_list;
+ struct sof_hdmi_private hdmi;
int pcm_count;
int dai_index;
const char *platform_name;
- bool common_hdmi_codec_drv;
- bool idisp_codec;
+ bool bt_offload_present;
+ int ssp_bt;
};
extern struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS];
int skl_hda_hdmi_jack_init(struct snd_soc_card *card);
int skl_hda_hdmi_add_pcm(struct snd_soc_card *card, int device);
-/*
- * Search card topology and register HDMI PCM related controls
- * to codec driver.
- */
-static inline int skl_hda_hdmi_build_controls(struct snd_soc_card *card)
-{
- struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
- struct snd_soc_component *component;
- struct skl_hda_hdmi_pcm *pcm;
-
- /* HDMI disabled, do not create controls */
- if (list_empty(&ctx->hdmi_pcm_list))
- return 0;
-
- pcm = list_first_entry(&ctx->hdmi_pcm_list, struct skl_hda_hdmi_pcm,
- head);
- component = pcm->codec_dai->component;
- if (!component)
- return -EINVAL;
-
- return hda_dsp_hdmi_build_controls(card, component);
-}
-
#endif /* __SOUND_SOC_HDA_DSP_COMMON_H */
diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c
index 88d91c0280bb..225867bb3310 100644
--- a/sound/soc/intel/boards/skl_hda_dsp_generic.c
+++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c
@@ -13,7 +13,6 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-acpi.h>
-#include "../../codecs/hdac_hdmi.h"
#include "skl_hda_dsp_common.h"
static const struct snd_soc_dapm_widget skl_hda_widgets[] = {
@@ -76,7 +75,7 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
link->platforms->name = ctx->platform_name;
link->nonatomic = 1;
- if (!ctx->idisp_codec)
+ if (!ctx->hdmi.idisp_codec)
return 0;
if (strstr(link->name, "HDMI")) {
@@ -95,32 +94,32 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
#define IDISP_DAI_COUNT 3
#define HDAC_DAI_COUNT 2
#define DMIC_DAI_COUNT 2
+#define BT_DAI_COUNT 1
/* there are two routes per iDisp output */
#define IDISP_ROUTE_COUNT (IDISP_DAI_COUNT * 2)
-#define IDISP_CODEC_MASK 0x4
#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000
-static int skl_hda_fill_card_info(struct snd_soc_card *card,
+static int skl_hda_fill_card_info(struct device *dev, struct snd_soc_card *card,
struct snd_soc_acpi_mach_params *mach_params)
{
struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_dai_link *dai_link;
+ struct snd_soc_dai_link *bt_link;
u32 codec_count, codec_mask;
int i, num_links, num_route;
codec_mask = mach_params->codec_mask;
codec_count = hweight_long(codec_mask);
- ctx->idisp_codec = !!(codec_mask & IDISP_CODEC_MASK);
if (!codec_count || codec_count > 2 ||
- (codec_count == 2 && !ctx->idisp_codec))
+ (codec_count == 2 && !ctx->hdmi.idisp_codec))
return -EINVAL;
if (codec_mask == IDISP_CODEC_MASK) {
/* topology with iDisp as the only HDA codec */
- num_links = IDISP_DAI_COUNT + DMIC_DAI_COUNT;
+ num_links = IDISP_DAI_COUNT + DMIC_DAI_COUNT + BT_DAI_COUNT;
num_route = IDISP_ROUTE_COUNT;
/*
@@ -129,7 +128,7 @@ static int skl_hda_fill_card_info(struct snd_soc_card *card,
* num_links of dai links need to be registered
* to ASoC.
*/
- for (i = 0; i < DMIC_DAI_COUNT; i++) {
+ for (i = 0; i < (DMIC_DAI_COUNT + BT_DAI_COUNT); i++) {
skl_hda_be_dai_links[IDISP_DAI_COUNT + i] =
skl_hda_be_dai_links[IDISP_DAI_COUNT +
HDAC_DAI_COUNT + i];
@@ -140,7 +139,7 @@ static int skl_hda_fill_card_info(struct snd_soc_card *card,
num_route = ARRAY_SIZE(skl_hda_map);
card->dapm_widgets = skl_hda_widgets;
card->num_dapm_widgets = ARRAY_SIZE(skl_hda_widgets);
- if (!ctx->idisp_codec) {
+ if (!ctx->hdmi.idisp_codec) {
card->dapm_routes = &skl_hda_map[IDISP_ROUTE_COUNT];
num_route -= IDISP_ROUTE_COUNT;
for (i = 0; i < IDISP_DAI_COUNT; i++) {
@@ -150,6 +149,28 @@ static int skl_hda_fill_card_info(struct snd_soc_card *card,
}
}
+ if (!ctx->bt_offload_present) {
+ /* remove last link since bt audio offload is not supported */
+ num_links -= BT_DAI_COUNT;
+ } else {
+ if (codec_mask == IDISP_CODEC_MASK)
+ bt_link = &skl_hda_be_dai_links[IDISP_DAI_COUNT + DMIC_DAI_COUNT];
+ else
+ bt_link = &skl_hda_be_dai_links[IDISP_DAI_COUNT + HDAC_DAI_COUNT + DMIC_DAI_COUNT];
+
+ /* complete the link name and dai name with SSP port number */
+ bt_link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT",
+ ctx->ssp_bt);
+ if (!bt_link->name)
+ return -ENOMEM;
+
+ bt_link->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+ "SSP%d Pin",
+ ctx->ssp_bt);
+ if (!bt_link->cpus->dai_name)
+ return -ENOMEM;
+ }
+
card->num_links = num_links;
card->num_dapm_routes = num_route;
@@ -184,7 +205,7 @@ static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card)
static int skl_hda_audio_probe(struct platform_device *pdev)
{
- struct snd_soc_acpi_mach *mach;
+ struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
struct skl_hda_private *ctx;
struct snd_soc_card *card;
int ret;
@@ -195,12 +216,6 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
if (!ctx)
return -ENOMEM;
- INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
-
- mach = pdev->dev.platform_data;
- if (!mach)
- return -EINVAL;
-
card = &ctx->card;
card->name = "hda-dsp",
card->owner = THIS_MODULE,
@@ -213,7 +228,15 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(card, ctx);
- ret = skl_hda_fill_card_info(card, &mach->mach_params);
+ if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
+ ctx->hdmi.idisp_codec = true;
+
+ if (hweight_long(mach->mach_params.bt_link_mask) == 1) {
+ ctx->bt_offload_present = true;
+ ctx->ssp_bt = fls(mach->mach_params.bt_link_mask) - 1;
+ }
+
+ ret = skl_hda_fill_card_info(&pdev->dev, card, &mach->mach_params);
if (ret < 0) {
dev_err(&pdev->dev, "Unsupported HDAudio/iDisp configuration found\n");
return ret;
@@ -222,7 +245,6 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
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;
card->dev = &pdev->dev;
if (!snd_soc_acpi_sof_parent(&pdev->dev))
diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index 2a88efaa6d26..578271b4230a 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -681,7 +681,7 @@ static int sof_es8336_probe(struct platform_device *pdev)
dai_links[0].codecs->dai_name = "ES8326 HiFi";
} else {
dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
- return -ENXIO;
+ return -ENOENT;
}
codec_dev = acpi_get_first_physical_node(adev);
@@ -818,6 +818,16 @@ static const struct platform_device_id board_ids[] = {
SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK |
SOF_ES8336_JD_INVERTED),
},
+ {
+ .name = "arl_es83x6_c1_h02",
+ .driver_data = (kernel_ulong_t)(SOF_ES8336_SSP_CODEC(1) |
+ SOF_NO_OF_HDMI_CAPTURE_SSP(2) |
+ SOF_HDMI_CAPTURE_1_SSP(0) |
+ SOF_HDMI_CAPTURE_2_SSP(2) |
+ SOF_SSP_HDMI_CAPTURE_PRESENT |
+ SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK |
+ SOF_ES8336_JD_INVERTED),
+ },
{ }
};
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 b1fb6fabd3b7..855109d22131 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -17,7 +17,7 @@
#include "sof_sdw_common.h"
#include "../../codecs/rt711.h"
-unsigned long sof_sdw_quirk = RT711_JD1;
+static unsigned long sof_sdw_quirk = RT711_JD1;
static int quirk_override = -1;
module_param_named(quirk, quirk_override, int, 0444);
MODULE_PARM_DESC(quirk, "Board-specific quirk override");
@@ -480,6 +480,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
RT711_JD2),
},
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF9")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
/* MeteorLake devices */
{
.callback = sof_sdw_quirk_cb,
@@ -540,6 +548,56 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
},
.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
},
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDB")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDC")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDD")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF8")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+
+ /* ArrowLake devices */
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE8")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF7")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
{}
};
@@ -1102,8 +1160,17 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
/* enable dmic01 & dmic16k */
- if (sof_sdw_quirk & SOC_SDW_PCH_DMIC || mach_params->dmic_num)
- dmic_num = 2;
+ if (sof_sdw_quirk & SOC_SDW_PCH_DMIC || mach_params->dmic_num) {
+ if (ctx->ignore_internal_dmic)
+ dev_warn(dev, "Ignoring PCH DMIC\n");
+ else
+ dmic_num = 2;
+ }
+ /*
+ * mach_params->dmic_num will be used to set the cfg-mics value of card->components
+ * string. Overwrite it to the actual number of PCH DMICs used in the device.
+ */
+ mach_params->dmic_num = dmic_num;
if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
bt_num = 1;
@@ -1148,14 +1215,10 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
}
/* dmic */
- if (dmic_num > 0) {
- if (ctx->ignore_internal_dmic) {
- dev_warn(dev, "Ignoring PCH DMIC\n");
- } else {
- ret = create_dmic_dailinks(card, &dai_links, &be_id);
- if (ret)
- goto err_end;
- }
+ if (dmic_num) {
+ ret = create_dmic_dailinks(card, &dai_links, &be_id);
+ if (ret)
+ goto err_end;
}
/* HDMI */
diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h
index c10d2711b730..3aa1dcec5172 100644
--- a/sound/soc/intel/boards/sof_sdw_common.h
+++ b/sound/soc/intel/boards/sof_sdw_common.h
@@ -58,8 +58,6 @@ struct intel_mc_ctx {
unsigned int sdw_pin_index[SDW_INTEL_MAX_LINKS];
};
-extern unsigned long sof_sdw_quirk;
-
/* generic HDMI support */
int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd);
diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c
index b2d02cc92a6a..0a5ce34d7f7b 100644
--- a/sound/soc/intel/boards/sof_wm8804.c
+++ b/sound/soc/intel/boards/sof_wm8804.c
@@ -270,7 +270,11 @@ static int sof_wm8804_probe(struct platform_device *pdev)
snprintf(codec_name, sizeof(codec_name),
"%s%s", "i2c-", acpi_dev_name(adev));
dailink[dai_index].codecs->name = codec_name;
+ } else {
+ dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+ return -ENOENT;
}
+
acpi_dev_put(adev);
snd_soc_card_set_drvdata(card, ctx);
diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
index 4167b2e9bc6a..bb1324fb588e 100644
--- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
@@ -35,6 +35,86 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
.group_id = 1,
};
+static const struct snd_soc_acpi_endpoint spk_2_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 2,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_endpoint spk_3_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 3,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_2_r_adr[] = {
+ {
+ .adr = 0x00023201FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "AMP3"
+ },
+ {
+ .adr = 0x00023301FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_3_endpoint,
+ .name_prefix = "AMP4"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_3_l_adr[] = {
+ {
+ .adr = 0x00033001fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "AMP1"
+ },
+ {
+ .adr = 0x00033101fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_2_endpoint,
+ .name_prefix = "AMP2"
+ }
+};
+
+static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
+ { /* Jack Playback Endpoint */
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* DMIC Capture Endpoint */
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Jack Capture Endpoint */
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Speaker Playback Endpoint */
+ .num = 3,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
+static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = {
+ {
+ .adr = 0x00003001FA424301ull,
+ .num_endpoints = ARRAY_SIZE(cs42l43_endpoints),
+ .endpoints = cs42l43_endpoints,
+ .name_prefix = "cs42l43"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt711_0_adr[] = {
{
.adr = 0x000020025D071100ull,
@@ -416,6 +496,25 @@ static const struct snd_soc_acpi_adr_device rt5682_0_adr[] = {
}
};
+static const struct snd_soc_acpi_link_adr adl_cs42l43_l0_cs35l56_l23[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(cs42l43_0_adr),
+ .adr_d = cs42l43_0_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(cs35l56_2_r_adr),
+ .adr_d = cs35l56_2_r_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(cs35l56_3_l_adr),
+ .adr_d = cs35l56_3_l_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr adl_rvp[] = {
{
.mask = BIT(0),
@@ -561,6 +660,12 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_adl_machines);
/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = {
{
+ .link_mask = BIT(0) | BIT(2) | BIT(3),
+ .links = adl_cs42l43_l0_cs35l56_l23,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-adl-cs42l43-l0-cs35l56-l23.tplg",
+ },
+ {
.link_mask = 0xF, /* 4 active links required */
.links = adl_default,
.drv_name = "sof_sdw",
diff --git a/sound/soc/intel/common/soc-acpi-intel-arl-match.c b/sound/soc/intel/common/soc-acpi-intel-arl-match.c
index cc87c34e5a08..9936a4b4eee7 100644
--- a/sound/soc/intel/common/soc-acpi-intel-arl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-arl-match.c
@@ -15,6 +15,112 @@ static const struct snd_soc_acpi_endpoint single_endpoint = {
.group_id = 0,
};
+static const struct snd_soc_acpi_endpoint spk_l_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 0,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 1,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_endpoint spk_2_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 2,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_endpoint spk_3_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 3,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_2_lr_adr[] = {
+ {
+ .adr = 0x00023001FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "AMP1"
+ },
+ {
+ .adr = 0x00023101FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "AMP2"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_3_lr_adr[] = {
+ {
+ .adr = 0x00033001FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "AMP1"
+ },
+ {
+ .adr = 0x00033401FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "AMP2"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_2_r_adr[] = {
+ {
+ .adr = 0x00023201FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "AMP3"
+ },
+ {
+ .adr = 0x00023301FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_3_endpoint,
+ .name_prefix = "AMP4"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_3_l_adr[] = {
+ {
+ .adr = 0x00033001fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "AMP1"
+ },
+ {
+ .adr = 0x00033101fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_2_endpoint,
+ .name_prefix = "AMP2"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_2_r1_adr[] = {
+ {
+ .adr = 0x00023101FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "AMP2"
+ },
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_3_l1_adr[] = {
+ {
+ .adr = 0x00033301fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "AMP1"
+ },
+};
+
static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
{ /* Jack Playback Endpoint */
.num = 0,
@@ -51,6 +157,15 @@ static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device cs42l43_2_adr[] = {
+ {
+ .adr = 0x00023001FA424301ull,
+ .num_endpoints = ARRAY_SIZE(cs42l43_endpoints),
+ .endpoints = cs42l43_endpoints,
+ .name_prefix = "cs42l43"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt711_0_adr[] = {
{
.adr = 0x000020025D071100ull,
@@ -77,6 +192,80 @@ static const struct snd_soc_acpi_link_adr arl_cs42l43_l0[] = {
},
};
+static const struct snd_soc_acpi_link_adr arl_cs42l43_l2[] = {
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(cs42l43_2_adr),
+ .adr_d = cs42l43_2_adr,
+ },
+};
+
+static const struct snd_soc_acpi_link_adr arl_cs42l43_l2_cs35l56_l3[] = {
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(cs42l43_2_adr),
+ .adr_d = cs42l43_2_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(cs35l56_3_lr_adr),
+ .adr_d = cs35l56_3_lr_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr arl_cs42l43_l0_cs35l56_l2[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(cs42l43_0_adr),
+ .adr_d = cs42l43_0_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(cs35l56_2_lr_adr),
+ .adr_d = cs35l56_2_lr_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr arl_cs42l43_l0_cs35l56_l23[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(cs42l43_0_adr),
+ .adr_d = cs42l43_0_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(cs35l56_2_r_adr),
+ .adr_d = cs35l56_2_r_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(cs35l56_3_l_adr),
+ .adr_d = cs35l56_3_l_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr arl_cs42l43_l0_cs35l56_2_l23[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(cs42l43_0_adr),
+ .adr_d = cs42l43_0_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(cs35l56_2_r1_adr),
+ .adr_d = cs35l56_2_r1_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(cs35l56_3_l1_adr),
+ .adr_d = cs35l56_3_l1_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr arl_rvp[] = {
{
.mask = BIT(0),
@@ -95,7 +284,32 @@ static const struct snd_soc_acpi_link_adr arl_sdca_rvp[] = {
{}
};
+static const struct snd_soc_acpi_codecs arl_essx_83x6 = {
+ .num_codecs = 3,
+ .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
+};
+
+static const struct snd_soc_acpi_codecs arl_lt6911_hdmi = {
+ .num_codecs = 1,
+ .codecs = {"INTC10B0"}
+};
+
struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[] = {
+ {
+ .comp_ids = &arl_essx_83x6,
+ .drv_name = "arl_es83x6_c1_h02",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &arl_lt6911_hdmi,
+ .sof_tplg_filename = "sof-arl-es83x6-ssp1-hdmi-ssp02.tplg",
+ },
+ {
+ .comp_ids = &arl_essx_83x6,
+ .drv_name = "sof-essx8336",
+ .sof_tplg_filename = "sof-arl-es8336", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER |
+ SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
+ SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_arl_machines);
@@ -103,12 +317,42 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_arl_machines);
/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = {
{
+ .link_mask = BIT(0) | BIT(2) | BIT(3),
+ .links = arl_cs42l43_l0_cs35l56_l23,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-arl-cs42l43-l0-cs35l56-l23.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(2) | BIT(3),
+ .links = arl_cs42l43_l0_cs35l56_2_l23,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-arl-cs42l43-l0-cs35l56-l23.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(2),
+ .links = arl_cs42l43_l0_cs35l56_l2,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-arl-cs42l43-l0-cs35l56-l2.tplg",
+ },
+ {
.link_mask = BIT(0),
.links = arl_cs42l43_l0,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-arl-cs42l43-l0.tplg",
},
{
+ .link_mask = BIT(2),
+ .links = arl_cs42l43_l2,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-arl-cs42l43-l2.tplg",
+ },
+ {
+ .link_mask = BIT(2) | BIT(3),
+ .links = arl_cs42l43_l2_cs35l56_l3,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-arl-cs42l43-l2-cs35l56-l3.tplg",
+ },
+ {
.link_mask = 0x1, /* link0 required */
.links = arl_rvp,
.drv_name = "sof_sdw",
diff --git a/sound/soc/intel/common/soc-acpi-intel-hda-match.c b/sound/soc/intel/common/soc-acpi-intel-hda-match.c
index 007ccd8a60e5..e93336e27beb 100644
--- a/sound/soc/intel/common/soc-acpi-intel-hda-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-hda-match.c
@@ -13,16 +13,8 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_hda_machines[] = {
{
/* .id is not used in this file */
.drv_name = "skl_hda_dsp_generic",
-
- /* .fw_filename is dynamically set in skylake driver */
-
- .sof_tplg_filename = "sof-hda-generic.tplg",
-
- /*
- * .machine_quirk and .quirk_data are not used here but
- * can be used if we need a more complicated machine driver
- * combining HDA+other device (e.g. DMIC).
- */
+ .sof_tplg_filename = "sof-hda-generic", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
},
{},
};
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 e6ffcd5be6c5..2522e6f11749 100644
--- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
@@ -36,6 +36,20 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
.group_id = 1,
};
+static const struct snd_soc_acpi_endpoint spk_2_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 2,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_endpoint spk_3_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 3,
+ .group_id = 1,
+};
+
static const struct snd_soc_acpi_endpoint rt712_endpoints[] = {
{
.num = 0,
@@ -103,6 +117,51 @@ static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
},
};
+static const struct snd_soc_acpi_adr_device cs35l56_2_l_adr[] = {
+ {
+ .adr = 0x00023001FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "AMP1"
+ },
+ {
+ .adr = 0x00023101FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_2_endpoint,
+ .name_prefix = "AMP2"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_3_r_adr[] = {
+ {
+ .adr = 0x00033201fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "AMP3"
+ },
+ {
+ .adr = 0x00033301fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_3_endpoint,
+ .name_prefix = "AMP4"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_3_lr_adr[] = {
+ {
+ .adr = 0x00033001fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "AMP1"
+ },
+ {
+ .adr = 0x00033101fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "AMP2"
+ }
+};
+
static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = {
{
.adr = 0x00003001FA424301ull,
@@ -210,6 +269,39 @@ static const struct snd_soc_acpi_link_adr lnl_cs42l43_l0[] = {
},
};
+static const struct snd_soc_acpi_link_adr lnl_cs42l43_l0_cs35l56_l3[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(cs42l43_0_adr),
+ .adr_d = cs42l43_0_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(cs35l56_3_lr_adr),
+ .adr_d = cs35l56_3_lr_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr lnl_cs42l43_l0_cs35l56_l23[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(cs42l43_0_adr),
+ .adr_d = cs42l43_0_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(cs35l56_2_l_adr),
+ .adr_d = cs35l56_2_l_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(cs35l56_3_r_adr),
+ .adr_d = cs35l56_3_r_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr lnl_rvp[] = {
{
.mask = BIT(0),
@@ -313,6 +405,18 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = {
.sof_tplg_filename = "sof-lnl-rt711-l0-rt1316-l23-rt714-l1.tplg",
},
{
+ .link_mask = BIT(0) | BIT(2) | BIT(3),
+ .links = lnl_cs42l43_l0_cs35l56_l23,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-lnl-cs42l43-l0-cs35l56-l23.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(3),
+ .links = lnl_cs42l43_l0_cs35l56_l3,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-lnl-cs42l43-l0-cs35l56-l3.tplg",
+ },
+ {
.link_mask = BIT(0),
.links = lnl_cs42l43_l0,
.drv_name = "sof_sdw",
diff --git a/sound/soc/sdw_utils/soc_sdw_rt_amp.c b/sound/soc/sdw_utils/soc_sdw_rt_amp.c
index 42be01405ab4..6951dfb56526 100644
--- a/sound/soc/sdw_utils/soc_sdw_rt_amp.c
+++ b/sound/soc/sdw_utils/soc_sdw_rt_amp.c
@@ -160,6 +160,13 @@ static const struct snd_soc_dapm_route rt1318_map[] = {
{ "Speaker", NULL, "rt1318-2 SPOR" },
};
+static const struct snd_soc_dapm_route rt1320_map[] = {
+ { "Speaker", NULL, "rt1320-1 SPOL" },
+ { "Speaker", NULL, "rt1320-1 SPOR" },
+ { "Speaker", NULL, "rt1320-2 SPOL" },
+ { "Speaker", NULL, "rt1320-2 SPOR" },
+};
+
static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_dai *dai,
char *codec_name)
{
@@ -171,8 +178,10 @@ static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_
return rt1308_map;
else if (strcmp(codec_name, "rt1316") == 0)
return rt1316_map;
- else
+ else if (strcmp(codec_name, "rt1318") == 0)
return rt1318_map;
+ else
+ return rt1320_map;
}
int asoc_sdw_rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index e8d0f199155d..d59ccb56642c 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -255,6 +255,25 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .part_id = 0x1320,
+ .dais = {
+ {
+ .direction = {true, false},
+ .dai_name = "rt1320-aif1",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .init = asoc_sdw_rt_amp_init,
+ .exit = asoc_sdw_rt_amp_exit,
+ .rtd_init = asoc_sdw_rt_amp_spk_rtd_init,
+ .controls = generic_spk_controls,
+ .num_controls = ARRAY_SIZE(generic_spk_controls),
+ .widgets = generic_spk_widgets,
+ .num_widgets = ARRAY_SIZE(generic_spk_widgets),
+ },
+ },
+ .dai_num = 1,
+ },
+ {
.part_id = 0x714,
.version_id = 3,
.ignore_internal_dmic = true,
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 5a40b8fbbbd3..d0a41e8e6334 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -444,6 +444,10 @@ static int mclk_id_override = -1;
module_param_named(mclk_id, mclk_id_override, int, 0444);
MODULE_PARM_DESC(mclk_id, "SOF SSP mclk_id");
+static int bt_link_mask_override;
+module_param_named(bt_link_mask, bt_link_mask_override, int, 0444);
+MODULE_PARM_DESC(bt_link_mask, "SOF BT offload link mask");
+
static int hda_init(struct snd_sof_dev *sdev)
{
struct hda_bus *hbus;
@@ -511,6 +515,8 @@ static int check_dmic_num(struct snd_sof_dev *sdev)
if (nhlt)
dmic_num = intel_nhlt_get_dmic_geo(sdev->dev, nhlt);
+ dev_info(sdev->dev, "DMICs detected in NHLT tables: %d\n", dmic_num);
+
/* allow for module parameter override */
if (dmic_num_override != -1) {
dev_dbg(sdev->dev,
@@ -527,7 +533,7 @@ static int check_dmic_num(struct snd_sof_dev *sdev)
return dmic_num;
}
-static int check_nhlt_ssp_mask(struct snd_sof_dev *sdev)
+static int check_nhlt_ssp_mask(struct snd_sof_dev *sdev, u8 device_type)
{
struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
struct nhlt_acpi_table *nhlt;
@@ -538,9 +544,11 @@ static int check_nhlt_ssp_mask(struct snd_sof_dev *sdev)
return ssp_mask;
if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP)) {
- ssp_mask = intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S);
+ ssp_mask = intel_nhlt_ssp_endpoint_mask(nhlt, device_type);
if (ssp_mask)
- dev_info(sdev->dev, "NHLT_DEVICE_I2S detected, ssp_mask %#x\n", ssp_mask);
+ dev_info(sdev->dev, "NHLT device %s(%d) detected, ssp_mask %#x\n",
+ device_type == NHLT_DEVICE_BT ? "BT" : "I2S",
+ device_type, ssp_mask);
}
return ssp_mask;
@@ -558,82 +566,6 @@ static int check_nhlt_ssp_mclk_mask(struct snd_sof_dev *sdev, int ssp_num)
return intel_nhlt_ssp_mclk_mask(nhlt, ssp_num);
}
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
-
-static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
- const char *sof_tplg_filename,
- const char *idisp_str,
- const char *dmic_str)
-{
- const char *tplg_filename = NULL;
- char *filename, *tmp;
- const char *split_ext;
-
- filename = kstrdup(sof_tplg_filename, GFP_KERNEL);
- if (!filename)
- return NULL;
-
- /* this assumes a .tplg extension */
- tmp = filename;
- split_ext = strsep(&tmp, ".");
- if (split_ext)
- tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
- "%s%s%s.tplg",
- split_ext, idisp_str, dmic_str);
- kfree(filename);
-
- return tplg_filename;
-}
-
-static int dmic_detect_topology_fixup(struct snd_sof_dev *sdev,
- const char **tplg_filename,
- const char *idisp_str,
- int *dmic_found,
- bool tplg_fixup)
-{
- const char *dmic_str;
- int dmic_num;
-
- /* first check for DMICs (using NHLT or module parameter) */
- dmic_num = check_dmic_num(sdev);
-
- switch (dmic_num) {
- case 1:
- dmic_str = "-1ch";
- break;
- case 2:
- dmic_str = "-2ch";
- break;
- case 3:
- dmic_str = "-3ch";
- break;
- case 4:
- dmic_str = "-4ch";
- break;
- default:
- dmic_num = 0;
- dmic_str = "";
- break;
- }
-
- if (tplg_fixup) {
- const char *default_tplg_filename = *tplg_filename;
- const char *fixed_tplg_filename;
-
- fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename,
- idisp_str, dmic_str);
- if (!fixed_tplg_filename)
- return -ENOMEM;
- *tplg_filename = fixed_tplg_filename;
- }
-
- dev_info(sdev->dev, "DMICs detected in NHLT tables: %d\n", dmic_num);
- *dmic_found = dmic_num;
-
- return 0;
-}
-#endif
-
static int hda_init_caps(struct snd_sof_dev *sdev)
{
u32 interface_mask = hda_get_interface_mask(sdev);
@@ -1045,10 +977,7 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
struct snd_soc_acpi_mach *hda_mach;
struct snd_sof_pdata *pdata = sdev->pdata;
const char *tplg_filename;
- const char *idisp_str;
- int dmic_num = 0;
int codec_num = 0;
- int ret;
int i;
/* codec detection */
@@ -1071,33 +1000,30 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
* - one external HDAudio codec
*/
if (!*mach && codec_num <= 2) {
- bool tplg_fixup;
+ bool tplg_fixup = false;
hda_mach = snd_soc_acpi_intel_hda_machines;
dev_info(bus->dev, "using HDA machine driver %s now\n",
hda_mach->drv_name);
- if (codec_num == 1 && HDA_IDISP_CODEC(bus->codec_mask))
- idisp_str = "-idisp";
- else
- idisp_str = "";
-
- /* topology: use the info from hda_machines */
- if (pdata->tplg_filename) {
- tplg_fixup = false;
- tplg_filename = pdata->tplg_filename;
- } else {
+ /*
+ * topology: use the info from hda_machines since tplg file name
+ * is not overwritten
+ */
+ if (!pdata->tplg_filename)
tplg_fixup = true;
- tplg_filename = hda_mach->sof_tplg_filename;
- }
- ret = dmic_detect_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num,
- tplg_fixup);
- if (ret < 0)
- return;
- hda_mach->mach_params.dmic_num = dmic_num;
- pdata->tplg_filename = tplg_filename;
+ if (tplg_fixup &&
+ codec_num == 1 && HDA_IDISP_CODEC(bus->codec_mask)) {
+ tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
+ "%s-idisp",
+ hda_mach->sof_tplg_filename);
+ if (!tplg_filename)
+ return;
+
+ hda_mach->sof_tplg_filename = tplg_filename;
+ }
if (codec_num == 2 ||
(codec_num == 1 && !HDA_IDISP_CODEC(bus->codec_mask))) {
@@ -1205,45 +1131,10 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
break;
}
if (mach && mach->link_mask) {
- int dmic_num = 0;
- bool tplg_fixup;
- const char *tplg_filename;
-
mach->mach_params.links = mach->links;
mach->mach_params.link_mask = mach->link_mask;
mach->mach_params.platform = dev_name(sdev->dev);
- if (pdata->tplg_filename) {
- tplg_fixup = false;
- } else {
- tplg_fixup = true;
- tplg_filename = mach->sof_tplg_filename;
- }
-
- /*
- * DMICs use up to 4 pins and are typically pin-muxed with SoundWire
- * link 2 and 3, or link 1 and 2, thus we only try to enable dmics
- * if all conditions are true:
- * a) 2 or fewer links are used by SoundWire
- * b) the NHLT table reports the presence of microphones
- */
- if (hweight_long(mach->link_mask) <= 2) {
- int ret;
-
- ret = dmic_detect_topology_fixup(sdev, &tplg_filename, "",
- &dmic_num, tplg_fixup);
- if (ret < 0)
- return NULL;
- }
- if (tplg_fixup)
- pdata->tplg_filename = tplg_filename;
- mach->mach_params.dmic_num = dmic_num;
-
- dev_dbg(sdev->dev,
- "SoundWire machine driver %s topology %s\n",
- mach->drv_name,
- pdata->tplg_filename);
-
return mach;
}
@@ -1300,6 +1191,19 @@ static int check_tplg_quirk_mask(struct snd_soc_acpi_mach *mach)
return 0;
}
+static char *remove_file_ext(const char *tplg_filename)
+{
+ char *filename, *tmp;
+
+ filename = kstrdup(tplg_filename, GFP_KERNEL);
+ if (!filename)
+ return NULL;
+
+ /* remove file extension if exist */
+ tmp = filename;
+ return strsep(&tmp, ".");
+}
+
struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
{
u32 interface_mask = hda_get_interface_mask(sdev);
@@ -1311,21 +1215,75 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
const char *tplg_filename;
const char *tplg_suffix;
bool amp_name_valid;
+ bool i2s_mach_found = false;
+ bool sdw_mach_found = false;
/* Try I2S or DMIC if it is supported */
- if (interface_mask & (BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC)))
+ if (interface_mask & (BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC))) {
mach = snd_soc_acpi_find_machine(desc->machines);
+ if (mach)
+ i2s_mach_found = true;
+ }
+
+ /*
+ * If I2S fails and no external HDaudio codec is detected,
+ * try SoundWire if it is supported
+ */
+ if (!mach && !HDA_EXT_CODEC(bus->codec_mask) &&
+ (interface_mask & BIT(SOF_DAI_INTEL_ALH))) {
+ mach = hda_sdw_machine_select(sdev);
+ if (mach)
+ sdw_mach_found = true;
+ }
+
+ /*
+ * Choose HDA generic machine driver if mach is NULL.
+ * Otherwise, set certain mach params.
+ */
+ hda_generic_machine_select(sdev, &mach);
+ if (!mach) {
+ dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
+ return NULL;
+ }
+
+ /* report BT offload link mask to machine driver */
+ mach->mach_params.bt_link_mask = check_nhlt_ssp_mask(sdev, NHLT_DEVICE_BT);
+
+ dev_info(sdev->dev, "BT link detected in NHLT tables: %#x\n",
+ mach->mach_params.bt_link_mask);
+
+ /* allow for module parameter override */
+ if (bt_link_mask_override) {
+ dev_dbg(sdev->dev, "overriding BT link detected in NHLT tables %#x by kernel param %#x\n",
+ mach->mach_params.bt_link_mask, bt_link_mask_override);
+ mach->mach_params.bt_link_mask = bt_link_mask_override;
+ }
+
+ if (hweight_long(mach->mach_params.bt_link_mask) > 1) {
+ dev_warn(sdev->dev, "invalid BT link mask %#x found, reset the mask\n",
+ mach->mach_params.bt_link_mask);
+ mach->mach_params.bt_link_mask = 0;
+ }
+ /*
+ * Fixup tplg file name by appending dmic num, ssp num, codec/amplifier
+ * name string if quirk flag is set.
+ */
if (mach) {
- bool add_extension = false;
bool tplg_fixup = false;
+ bool dmic_fixup = false;
/*
* If tplg file name is overridden, use it instead of
* the one set in mach table
*/
if (!sof_pdata->tplg_filename) {
- sof_pdata->tplg_filename = mach->sof_tplg_filename;
+ /* remove file extension if it exists */
+ tplg_filename = remove_file_ext(mach->sof_tplg_filename);
+ if (!tplg_filename)
+ return NULL;
+
+ sof_pdata->tplg_filename = tplg_filename;
tplg_fixup = true;
}
@@ -1343,20 +1301,36 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
/* report to machine driver if any DMICs are found */
mach->mach_params.dmic_num = check_dmic_num(sdev);
+ if (sdw_mach_found) {
+ /*
+ * DMICs use up to 4 pins and are typically pin-muxed with SoundWire
+ * link 2 and 3, or link 1 and 2, thus we only try to enable dmics
+ * if all conditions are true:
+ * a) 2 or fewer links are used by SoundWire
+ * b) the NHLT table reports the presence of microphones
+ */
+ if (hweight_long(mach->link_mask) <= 2)
+ dmic_fixup = true;
+ else
+ mach->mach_params.dmic_num = 0;
+ } else {
+ if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER)
+ dmic_fixup = true;
+ }
+
if (tplg_fixup &&
- mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER &&
+ dmic_fixup &&
mach->mach_params.dmic_num) {
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s%s%d%s",
sof_pdata->tplg_filename,
- "-dmic",
+ i2s_mach_found ? "-dmic" : "-",
mach->mach_params.dmic_num,
"ch");
if (!tplg_filename)
return NULL;
sof_pdata->tplg_filename = tplg_filename;
- add_extension = true;
}
if (mach->link_mask) {
@@ -1365,7 +1339,7 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
}
/* report SSP link mask to machine driver */
- mach->mach_params.i2s_link_mask = check_nhlt_ssp_mask(sdev);
+ mach->mach_params.i2s_link_mask = check_nhlt_ssp_mask(sdev, NHLT_DEVICE_I2S);
if (tplg_fixup &&
mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER &&
@@ -1396,7 +1370,6 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
return NULL;
sof_pdata->tplg_filename = tplg_filename;
- add_extension = true;
mclk_mask = check_nhlt_ssp_mclk_mask(sdev, ssp_num);
@@ -1435,7 +1408,6 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
return NULL;
sof_pdata->tplg_filename = tplg_filename;
- add_extension = true;
}
@@ -1457,10 +1429,9 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
return NULL;
sof_pdata->tplg_filename = tplg_filename;
- add_extension = true;
}
- if (tplg_fixup && add_extension) {
+ if (tplg_fixup) {
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s%s",
sof_pdata->tplg_filename,
@@ -1479,22 +1450,6 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
}
}
- /*
- * If I2S fails and no external HDaudio codec is detected,
- * try SoundWire if it is supported
- */
- if (!mach && !HDA_EXT_CODEC(bus->codec_mask) &&
- (interface_mask & BIT(SOF_DAI_INTEL_ALH)))
- mach = hda_sdw_machine_select(sdev);
-
- /*
- * Choose HDA generic machine driver if mach is NULL.
- * Otherwise, set certain mach params.
- */
- hda_generic_machine_select(sdev, &mach);
- if (!mach)
- dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
-
return mach;
}