summaryrefslogtreecommitdiff
path: root/sound/soc/sdw_utils/soc_sdw_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sdw_utils/soc_sdw_utils.c')
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c757
1 files changed, 702 insertions, 55 deletions
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 937fa3ce59df..e440c2327100 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
+#include <sound/sdca_function.h>
#include <sound/soc_sdw_utils.h>
static const struct snd_soc_dapm_widget generic_dmic_widgets[] = {
@@ -34,16 +35,30 @@ static const struct snd_kcontrol_new generic_spk_controls[] = {
SOC_DAPM_PIN_SWITCH("Speaker"),
};
-static const struct snd_soc_dapm_widget maxim_widgets[] = {
+static const struct snd_soc_dapm_widget lr_spk_widgets[] = {
SND_SOC_DAPM_SPK("Left Spk", NULL),
SND_SOC_DAPM_SPK("Right Spk", NULL),
};
-static const struct snd_kcontrol_new maxim_controls[] = {
+static const struct snd_soc_dapm_widget lr_4spk_widgets[] = {
+ SND_SOC_DAPM_SPK("Left Spk", NULL),
+ SND_SOC_DAPM_SPK("Right Spk", NULL),
+ SND_SOC_DAPM_SPK("Left Spk2", NULL),
+ SND_SOC_DAPM_SPK("Right Spk2", NULL),
+};
+
+static const struct snd_kcontrol_new lr_spk_controls[] = {
SOC_DAPM_PIN_SWITCH("Left Spk"),
SOC_DAPM_PIN_SWITCH("Right Spk"),
};
+static const struct snd_kcontrol_new lr_4spk_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Left Spk"),
+ SOC_DAPM_PIN_SWITCH("Right Spk"),
+ SOC_DAPM_PIN_SWITCH("Left Spk2"),
+ SOC_DAPM_PIN_SWITCH("Right Spk2"),
+};
+
static const struct snd_soc_dapm_widget rt700_widgets[] = {
SND_SOC_DAPM_HP("Headphones", NULL),
SND_SOC_DAPM_MIC("AMIC", NULL),
@@ -58,7 +73,29 @@ static const struct snd_kcontrol_new rt700_controls[] = {
struct asoc_sdw_codec_info codec_info_list[] = {
{
+ .vendor_id = 0x0102,
+ .part_id = 0x0000, /* TAS2783A */
+ .name_prefix = "tas2783",
+ .dais = {
+ {
+ .direction = {true, true},
+ .dai_name = "tas2783-codec",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
+ .init = asoc_sdw_ti_amp_init,
+ .rtd_init = asoc_sdw_ti_spk_rtd_init,
+ .controls = lr_4spk_controls,
+ .num_controls = ARRAY_SIZE(lr_4spk_controls),
+ .widgets = lr_4spk_widgets,
+ .num_widgets = ARRAY_SIZE(lr_4spk_widgets),
+ },
+ },
+ .dai_num = 1,
+ },
+ {
+ .vendor_id = 0x025d,
.part_id = 0x700,
+ .name_prefix = "rt700",
.dais = {
{
.direction = {true, true},
@@ -75,7 +112,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x711,
+ .name_prefix = "rt711",
.version_id = 3,
.dais = {
{
@@ -95,7 +134,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x711,
+ .name_prefix = "rt711",
.version_id = 2,
.dais = {
{
@@ -115,7 +156,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x712,
+ .name_prefix = "rt712",
.version_id = 3,
.dais = {
{
@@ -134,6 +177,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
{
.direction = {true, false},
.dai_name = "rt712-sdca-aif2",
+ .component_name = "rt712",
.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,
@@ -150,12 +194,16 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_type = SOC_SDW_DAI_TYPE_MIC,
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
+ .quirk = SOC_SDW_CODEC_MIC,
+ .quirk_exclude = true,
},
},
.dai_num = 3,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x1712,
+ .name_prefix = "rt712-dmic",
.version_id = 3,
.dais = {
{
@@ -169,7 +217,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x713,
+ .name_prefix = "rt713",
.version_id = 3,
.dais = {
{
@@ -196,7 +246,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 2,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x1713,
+ .name_prefix = "rt713-dmic",
.version_id = 3,
.dais = {
{
@@ -210,12 +262,15 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x1308,
+ .name_prefix = "rt1308",
.acpi_id = "10EC1308",
.dais = {
{
.direction = {true, false},
.dai_name = "rt1308-aif",
+ .component_name = "rt1308",
.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,
@@ -231,11 +286,14 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.ops = &soc_sdw_rt1308_i2s_ops,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x1316,
+ .name_prefix = "rt1316",
.dais = {
{
.direction = {true, true},
.dai_name = "rt1316-aif",
+ .component_name = "rt1316",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
.init = asoc_sdw_rt_amp_init,
@@ -250,11 +308,14 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x1318,
+ .name_prefix = "rt1318",
.dais = {
{
.direction = {true, true},
.dai_name = "rt1318-aif",
+ .component_name = "rt1318",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
.init = asoc_sdw_rt_amp_init,
@@ -269,11 +330,15 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x1320,
+ .name_prefix = "rt1320",
+ .is_amp = true,
.dais = {
{
.direction = {true, false},
.dai_name = "rt1320-aif1",
+ .component_name = "rt1320",
.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,
@@ -284,11 +349,56 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.widgets = generic_spk_widgets,
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
},
+ {
+ .direction = {false, true},
+ .dai_name = "rt1320-aif2",
+ .component_name = "rt1320",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_rt_dmic_rtd_init,
+ .widgets = generic_dmic_widgets,
+ .num_widgets = ARRAY_SIZE(generic_dmic_widgets),
+ },
},
- .dai_num = 1,
+ .dai_num = 2,
},
{
+ .vendor_id = 0x025d,
+ .part_id = 0x1321,
+ .name_prefix = "rt1320",
+ .is_amp = true,
+ .dais = {
+ {
+ .direction = {true, false},
+ .dai_name = "rt1320-aif1",
+ .component_name = "rt1320",
+ .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),
+ },
+ {
+ .direction = {false, true},
+ .dai_name = "rt1320-aif2",
+ .component_name = "rt1320",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_rt_dmic_rtd_init,
+ .widgets = generic_dmic_widgets,
+ .num_widgets = ARRAY_SIZE(generic_dmic_widgets),
+ },
+ },
+ .dai_num = 2,
+ },
+ {
+ .vendor_id = 0x025d,
.part_id = 0x714,
+ .name_prefix = "rt714",
.version_id = 3,
.ignore_internal_dmic = true,
.dais = {
@@ -303,7 +413,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x715,
+ .name_prefix = "rt715",
.version_id = 3,
.ignore_internal_dmic = true,
.dais = {
@@ -318,7 +430,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x714,
+ .name_prefix = "rt714",
.version_id = 2,
.ignore_internal_dmic = true,
.dais = {
@@ -333,7 +447,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x715,
+ .name_prefix = "rt715",
.version_id = 2,
.ignore_internal_dmic = true,
.dais = {
@@ -348,7 +464,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x721,
+ .name_prefix = "rt721",
.version_id = 3,
.dais = {
{
@@ -367,6 +485,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
{
.direction = {true, false},
.dai_name = "rt721-sdca-aif2",
+ .component_name = "rt721",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
/* No feedback capability is provided by rt721-sdca codec driver*/
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
@@ -384,12 +503,16 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_type = SOC_SDW_DAI_TYPE_MIC,
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
+ .quirk = SOC_SDW_CODEC_MIC,
+ .quirk_exclude = true,
},
},
.dai_num = 3,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x722,
+ .name_prefix = "rt722",
.version_id = 3,
.dais = {
{
@@ -408,6 +531,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
{
.direction = {true, false},
.dai_name = "rt722-sdca-aif2",
+ .component_name = "rt722",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
/* No feedback capability is provided by rt722-sdca codec driver*/
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
@@ -427,48 +551,58 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_type = SOC_SDW_DAI_TYPE_MIC,
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
+ .quirk = SOC_SDW_CODEC_MIC,
+ .quirk_exclude = true,
},
},
.dai_num = 3,
},
{
+ .vendor_id = 0x019f,
.part_id = 0x8373,
+ .name_prefix = "Left",
.dais = {
{
.direction = {true, true},
.dai_name = "max98373-aif1",
+ .component_name = "mx8373",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
.init = asoc_sdw_maxim_init,
.rtd_init = asoc_sdw_maxim_spk_rtd_init,
- .controls = maxim_controls,
- .num_controls = ARRAY_SIZE(maxim_controls),
- .widgets = maxim_widgets,
- .num_widgets = ARRAY_SIZE(maxim_widgets),
+ .controls = lr_spk_controls,
+ .num_controls = ARRAY_SIZE(lr_spk_controls),
+ .widgets = lr_spk_widgets,
+ .num_widgets = ARRAY_SIZE(lr_spk_widgets),
},
},
.dai_num = 1,
},
{
+ .vendor_id = 0x019f,
.part_id = 0x8363,
+ .name_prefix = "Left",
.dais = {
{
.direction = {true, false},
.dai_name = "max98363-aif1",
+ .component_name = "mx8363",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
.init = asoc_sdw_maxim_init,
.rtd_init = asoc_sdw_maxim_spk_rtd_init,
- .controls = maxim_controls,
- .num_controls = ARRAY_SIZE(maxim_controls),
- .widgets = maxim_widgets,
- .num_widgets = ARRAY_SIZE(maxim_widgets),
+ .controls = lr_spk_controls,
+ .num_controls = ARRAY_SIZE(lr_spk_controls),
+ .widgets = lr_spk_widgets,
+ .num_widgets = ARRAY_SIZE(lr_spk_widgets),
},
},
.dai_num = 1,
},
{
+ .vendor_id = 0x025d,
.part_id = 0x5682,
+ .name_prefix = "rt5682",
.dais = {
{
.direction = {true, true},
@@ -485,13 +619,16 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x01fa,
.part_id = 0x3556,
+ .name_prefix = "AMP",
.dais = {
{
- .direction = {true, true},
+ .direction = {true, false},
.dai_name = "cs35l56-sdw1",
+ .component_name = "cs35l56",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
- .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
.init = asoc_sdw_cs_amp_init,
.rtd_init = asoc_sdw_cs_spk_rtd_init,
.controls = generic_spk_controls,
@@ -499,11 +636,76 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.widgets = generic_spk_widgets,
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
},
+ {
+ .direction = {false, true},
+ .dai_name = "cs35l56-sdw1c",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
+ .rtd_init = asoc_sdw_cs_spk_feedback_rtd_init,
+ },
},
- .dai_num = 1,
+ .dai_num = 2,
},
{
+ .vendor_id = 0x01fa,
+ .part_id = 0x3557,
+ .name_prefix = "AMP",
+ .dais = {
+ {
+ .direction = {true, false},
+ .dai_name = "cs35l56-sdw1",
+ .component_name = "cs35l56",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .init = asoc_sdw_cs_amp_init,
+ .rtd_init = asoc_sdw_cs_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),
+ },
+ {
+ .direction = {false, true},
+ .dai_name = "cs35l56-sdw1c",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
+ .rtd_init = asoc_sdw_cs_spk_feedback_rtd_init,
+ },
+ },
+ .dai_num = 2,
+ },
+ {
+ .vendor_id = 0x01fa,
+ .part_id = 0x3563,
+ .name_prefix = "AMP",
+ .dais = {
+ {
+ .direction = {true, false},
+ .dai_name = "cs35l56-sdw1",
+ .component_name = "cs35l56",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .init = asoc_sdw_cs_amp_init,
+ .rtd_init = asoc_sdw_cs_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),
+ },
+ {
+ .direction = {false, true},
+ .dai_name = "cs35l56-sdw1c",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
+ .rtd_init = asoc_sdw_cs_spk_feedback_rtd_init,
+ },
+ },
+ .dai_num = 2,
+ },
+ {
+ .vendor_id = 0x01fa,
.part_id = 0x4242,
+ .name_prefix = "cs42l42",
.dais = {
{
.direction = {true, true},
@@ -520,13 +722,71 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x01fa,
.part_id = 0x4243,
- .codec_name = "cs42l43-codec",
+ .name_prefix = "cs42l43",
+ .count_sidecar = asoc_sdw_bridge_cs35l56_count_sidecar,
+ .add_sidecar = asoc_sdw_bridge_cs35l56_add_sidecar,
+ .dais = {
+ {
+ .direction = {true, false},
+ .codec_name = "cs42l43-codec",
+ .dai_name = "cs42l43-dp5",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .rtd_init = asoc_sdw_cs42l43_hs_rtd_init,
+ .controls = generic_jack_controls,
+ .num_controls = ARRAY_SIZE(generic_jack_controls),
+ .widgets = generic_jack_widgets,
+ .num_widgets = ARRAY_SIZE(generic_jack_widgets),
+ },
+ {
+ .direction = {false, true},
+ .codec_name = "cs42l43-codec",
+ .dai_name = "cs42l43-dp1",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_cs42l43_dmic_rtd_init,
+ .widgets = generic_dmic_widgets,
+ .num_widgets = ARRAY_SIZE(generic_dmic_widgets),
+ .quirk = SOC_SDW_CODEC_MIC,
+ .quirk_exclude = true,
+ },
+ {
+ .direction = {false, true},
+ .codec_name = "cs42l43-codec",
+ .dai_name = "cs42l43-dp2",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
+ },
+ {
+ .direction = {true, false},
+ .codec_name = "cs42l43-codec",
+ .component_name = "cs42l43-spk",
+ .dai_name = "cs42l43-dp6",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .init = asoc_sdw_cs42l43_spk_init,
+ .rtd_init = asoc_sdw_cs42l43_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),
+ .quirk = SOC_SDW_CODEC_SPKR | SOC_SDW_SIDECAR_AMPS,
+ },
+ },
+ .dai_num = 4,
+ },
+ {
+ .vendor_id = 0x01fa,
+ .part_id = 0x2A3B,
+ .name_prefix = "cs42l43",
.count_sidecar = asoc_sdw_bridge_cs35l56_count_sidecar,
.add_sidecar = asoc_sdw_bridge_cs35l56_add_sidecar,
.dais = {
{
.direction = {true, false},
+ .codec_name = "cs42l43-codec",
.dai_name = "cs42l43-dp5",
.dai_type = SOC_SDW_DAI_TYPE_JACK,
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
@@ -538,6 +798,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.direction = {false, true},
+ .codec_name = "cs42l43-codec",
.dai_name = "cs42l43-dp1",
.dai_type = SOC_SDW_DAI_TYPE_MIC,
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
@@ -549,12 +810,14 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.direction = {false, true},
+ .codec_name = "cs42l43-codec",
.dai_name = "cs42l43-dp2",
.dai_type = SOC_SDW_DAI_TYPE_JACK,
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
},
{
.direction = {true, false},
+ .codec_name = "cs42l43-codec",
.dai_name = "cs42l43-dp6",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
@@ -570,7 +833,120 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 4,
},
{
+ .vendor_id = 0x01fa,
+ .part_id = 0x4245,
+ .name_prefix = "cs42l45",
+ .dais = {
+ {
+ .direction = {true, false},
+ .codec_name = "snd_soc_sdca.UAJ",
+ .dai_name = "IT 41",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .rtd_init = asoc_sdw_cs42l45_hs_rtd_init,
+ },
+ {
+ .direction = {false, true},
+ .codec_name = "snd_soc_sdca.SmartMic",
+ .dai_name = "OT 113",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_cs42l45_dmic_rtd_init,
+ },
+ {
+ .direction = {false, true},
+ .codec_name = "snd_soc_sdca.UAJ",
+ .dai_name = "OT 36",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
+ },
+ },
+ .dai_num = 3,
+ .auxs = {
+ {
+ .codec_name = "snd_soc_sdca.HID",
+ },
+ },
+ .aux_num = 1,
+ },
+ {
+ .vendor_id = 0x01fa,
+ .part_id = 0x4249,
+ .name_prefix = "cs42l45", /* Use same user-space as cs42l45 */
+ .dais = {
+ {
+ .direction = {true, false},
+ .codec_name = "snd_soc_sdca.UAJ",
+ .dai_name = "IT 41",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .rtd_init = asoc_sdw_cs42l45_hs_rtd_init,
+ },
+ {
+ .direction = {false, true},
+ .codec_name = "snd_soc_sdca.SmartMic",
+ .dai_name = "OT 113",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_cs42l45_dmic_rtd_init,
+ },
+ {
+ .direction = {false, true},
+ .codec_name = "snd_soc_sdca.UAJ",
+ .dai_name = "OT 36",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
+ },
+ },
+ .dai_num = 3,
+ .auxs = {
+ {
+ .codec_name = "snd_soc_sdca.HID",
+ },
+ },
+ .aux_num = 1,
+ },
+ {
+ .vendor_id = 0x01fa,
+ .part_id = 0x4747,
+ .name_prefix = "cs47l47",
+ .dais = {
+ {
+ .direction = {true, false},
+ .codec_name = "snd_soc_sdca.UAJ",
+ .dai_name = "IT 41",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .rtd_init = asoc_sdw_cs47l47_hs_rtd_init,
+ },
+ {
+ .direction = {false, true},
+ .codec_name = "snd_soc_sdca.SmartMic",
+ .dai_name = "OT 113",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_cs47l47_dmic_rtd_init,
+ },
+ {
+ .direction = {false, true},
+ .codec_name = "snd_soc_sdca.UAJ",
+ .dai_name = "OT 36",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
+ },
+ },
+ .dai_num = 3,
+ .auxs = {
+ {
+ .codec_name = "snd_soc_sdca.HID",
+ },
+ },
+ .aux_num = 1,
+ },
+ {
+ .vendor_id = 0x0105,
.part_id = 0xaaaa, /* generic codec mockup */
+ .name_prefix = "sdw_mockup_mmulti-function",
.version_id = 0,
.dais = {
{
@@ -579,11 +955,25 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_type = SOC_SDW_DAI_TYPE_JACK,
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
},
+ {
+ .direction = {true, false},
+ .dai_name = "sdw-mockup-aif1",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ },
+ {
+ .direction = {false, true},
+ .dai_name = "sdw-mockup-aif1",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ },
},
- .dai_num = 1,
+ .dai_num = 3,
},
{
+ .vendor_id = 0x0105,
.part_id = 0xaa55, /* headset codec mockup */
+ .name_prefix = "sdw_mockup_headset0",
.version_id = 0,
.dais = {
{
@@ -596,7 +986,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x0105,
.part_id = 0x55aa, /* amplifier mockup */
+ .name_prefix = "sdw_mockup_amp1",
.version_id = 0,
.dais = {
{
@@ -609,7 +1001,9 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .vendor_id = 0x0105,
.part_id = 0x5555,
+ .name_prefix = "sdw_mockup_mic0",
.version_id = 0,
.dais = {
{
@@ -632,9 +1026,10 @@ EXPORT_SYMBOL_NS(asoc_sdw_get_codec_info_list_count, "SND_SOC_SDW_UTILS");
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr)
{
- unsigned int part_id, sdw_version;
+ unsigned int vendor_id, part_id, sdw_version;
int i;
+ vendor_id = SDW_MFG_ID(adr);
part_id = SDW_PART_ID(adr);
sdw_version = SDW_VERSION(adr);
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
@@ -643,6 +1038,7 @@ struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr)
* version_id is not specified in the codec info.
*/
if (part_id == codec_info_list[i].part_id &&
+ vendor_id == codec_info_list[i].vendor_id &&
(!codec_info_list[i].version_id ||
sdw_version == codec_info_list[i].version_id))
return &codec_info_list[i];
@@ -651,6 +1047,20 @@ struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr)
}
EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_part, "SND_SOC_SDW_UTILS");
+static struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_sdw_id(const struct sdw_slave_id *id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
+ if (id->part_id == codec_info_list[i].part_id &&
+ id->mfg_id == codec_info_list[i].vendor_id &&
+ (!codec_info_list[i].version_id ||
+ id->sdw_version == codec_info_list[i].version_id))
+ return &codec_info_list[i];
+
+ return NULL;
+}
+
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_acpi(const u8 *acpi_id)
{
int i;
@@ -683,20 +1093,47 @@ struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_dai(const char *dai_name, i
}
EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_dai, "SND_SOC_SDW_UTILS");
+static int asoc_sdw_find_codec_info_dai_index(const struct asoc_sdw_codec_info *codec_info,
+ const char *dai_name)
+{
+ int i;
+
+ for (i = 0; i < codec_info->dai_num; i++) {
+ if (!strcmp(codec_info->dais[i].dai_name, dai_name))
+ return i;
+ }
+
+ return -ENOENT;
+}
+
int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
+ struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
struct asoc_sdw_codec_info *codec_info;
struct snd_soc_dai *dai;
+ struct sdw_slave *sdw_peripheral;
+ const char *spk_components = NULL;
int dai_index;
int ret;
int i;
for_each_rtd_codec_dais(rtd, i, dai) {
- codec_info = asoc_sdw_find_codec_info_dai(dai->name, &dai_index);
+ if (is_sdw_slave(dai->component->dev))
+ sdw_peripheral = dev_to_sdw_dev(dai->component->dev);
+ else if (dai->component->dev->parent && is_sdw_slave(dai->component->dev->parent))
+ sdw_peripheral = dev_to_sdw_dev(dai->component->dev->parent);
+ else
+ continue;
+
+ codec_info = asoc_sdw_find_codec_info_sdw_id(&sdw_peripheral->id);
if (!codec_info)
return -EINVAL;
+ dai_index = asoc_sdw_find_codec_info_dai_index(codec_info, dai->name);
+ WARN_ON(dai_index < 0);
+
/*
* A codec dai can be connected to different dai links for capture and playback,
* but we only need to call the rtd_init function once.
@@ -706,6 +1143,10 @@ int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
if (codec_info->dais[dai_index].rtd_init_done)
continue;
+ dev_dbg(card->dev, "%#x/%s initializing for %s/%s\n",
+ codec_info->part_id, codec_info->dais[dai_index].dai_name,
+ dai->component->name, dai->name);
+
/*
* Add card controls and dapm widgets for the first codec dai.
* The controls and widgets will be used for all codec dais.
@@ -718,18 +1159,18 @@ int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
ret = snd_soc_add_card_controls(card, codec_info->dais[dai_index].controls,
codec_info->dais[dai_index].num_controls);
if (ret) {
- dev_err(card->dev, "%#x controls addition failed: %d\n",
- codec_info->part_id, ret);
+ dev_err(card->dev, "%#x-%#x controls addition failed: %d\n",
+ codec_info->vendor_id, codec_info->part_id, ret);
return ret;
}
}
if (codec_info->dais[dai_index].widgets) {
- ret = snd_soc_dapm_new_controls(&card->dapm,
+ ret = snd_soc_dapm_new_controls(dapm,
codec_info->dais[dai_index].widgets,
codec_info->dais[dai_index].num_widgets);
if (ret) {
- dev_err(card->dev, "%#x widgets addition failed: %d\n",
- codec_info->part_id, ret);
+ dev_err(card->dev, "%#x-%#x widgets addition failed: %d\n",
+ codec_info->vendor_id, codec_info->part_id, ret);
return ret;
}
}
@@ -740,9 +1181,46 @@ skip_add_controls_widgets:
if (ret)
return ret;
}
+
+ /* Generate the spk component string for card->components string */
+ if (codec_info->dais[dai_index].dai_type == SOC_SDW_DAI_TYPE_AMP &&
+ codec_info->dais[dai_index].component_name) {
+ const char *component;
+
+ /*
+ * For the special case of cs42l43 with sidecar amps, use only
+ * "cs35l56-bridge" as the component name in card->components
+ */
+ if (ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS &&
+ !strcmp(codec_info->dais[dai_index].component_name, "cs42l43-spk"))
+ component = "cs35l56-bridge";
+ else
+ component = codec_info->dais[dai_index].component_name;
+
+ if (!spk_components)
+ spk_components =
+ devm_kasprintf(card->dev, GFP_KERNEL, "%s", component);
+ else
+ /* Append component name to spk_components */
+ spk_components =
+ devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s+%s", spk_components, component);
+
+ if (!spk_components)
+ return -ENOMEM;
+ }
+
codec_info->dais[dai_index].rtd_init_done = true;
}
+ if (spk_components) {
+ /* Update card components for speaker components */
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:%s",
+ card->components, spk_components);
+ if (!card->components)
+ return -ENOMEM;
+ }
+
return 0;
}
EXPORT_SYMBOL_NS(asoc_sdw_rtd_init, "SND_SOC_SDW_UTILS");
@@ -915,10 +1393,9 @@ static bool asoc_sdw_is_unique_device(const struct snd_soc_acpi_link_adr *adr_li
return true;
}
-const char *asoc_sdw_get_codec_name(struct device *dev,
- const struct asoc_sdw_codec_info *codec_info,
- const struct snd_soc_acpi_link_adr *adr_link,
- int adr_index)
+static const char *_asoc_sdw_get_codec_name(struct device *dev,
+ const struct snd_soc_acpi_link_adr *adr_link,
+ int adr_index)
{
u64 adr = adr_link->adr_d[adr_index].adr;
unsigned int sdw_version = SDW_VERSION(adr);
@@ -928,17 +1405,34 @@ const char *asoc_sdw_get_codec_name(struct device *dev,
unsigned int part_id = SDW_PART_ID(adr);
unsigned int class_id = SDW_CLASS_ID(adr);
- if (codec_info->codec_name)
- return devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL);
- else if (asoc_sdw_is_unique_device(adr_link, sdw_version, mfg_id, part_id,
- class_id, adr_index))
+ if (asoc_sdw_is_unique_device(adr_link, sdw_version, mfg_id, part_id,
+ class_id, adr_index))
return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x",
link_id, mfg_id, part_id, class_id);
- else
- return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x",
- link_id, mfg_id, part_id, class_id, unique_id);
- return NULL;
+ return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x",
+ link_id, mfg_id, part_id, class_id, unique_id);
+}
+
+const char *asoc_sdw_get_codec_name(struct device *dev,
+ const struct asoc_sdw_dai_info *dai_info,
+ const struct snd_soc_acpi_link_adr *adr_link,
+ int adr_index)
+{
+ if (dai_info->codec_name) {
+ struct snd_soc_component *component;
+
+ component = snd_soc_lookup_component_by_name(dai_info->codec_name);
+ if (component) {
+ dev_dbg(dev, "%s found component %s for codec_name %s\n",
+ __func__, component->name, dai_info->codec_name);
+ return devm_kstrdup(dev, component->name, GFP_KERNEL);
+ } else {
+ return devm_kstrdup(dev, dai_info->codec_name, GFP_KERNEL);
+ }
+ }
+
+ return _asoc_sdw_get_codec_name(dev, adr_link, adr_index);
}
EXPORT_SYMBOL_NS(asoc_sdw_get_codec_name, "SND_SOC_SDW_UTILS");
@@ -1040,9 +1534,8 @@ EXPORT_SYMBOL_NS(asoc_sdw_init_dai_link, "SND_SOC_SDW_UTILS");
int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
int *be_id, char *name, int playback, int capture,
const char *cpu_dai_name, const char *platform_comp_name,
- int num_platforms, const char *codec_name,
- const char *codec_dai_name, int no_pcm,
- int (*init)(struct snd_soc_pcm_runtime *rtd),
+ const char *codec_name, const char *codec_dai_name,
+ int no_pcm, int (*init)(struct snd_soc_pcm_runtime *rtd),
const struct snd_soc_ops *ops)
{
struct snd_soc_dai_link_component *dlc;
@@ -1059,14 +1552,15 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d
dlc[2].dai_name = codec_dai_name;
asoc_sdw_init_dai_link(dev, dai_links, be_id, name, playback, capture,
- &dlc[0], 1, &dlc[1], num_platforms,
- &dlc[2], 1, no_pcm, init, ops);
+ &dlc[0], 1, &dlc[1], 1, &dlc[2], 1,
+ no_pcm, init, ops);
return 0;
}
EXPORT_SYMBOL_NS(asoc_sdw_init_simple_dai_link, "SND_SOC_SDW_UTILS");
-int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends)
+int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card,
+ int *num_devs, int *num_ends, int *num_aux)
{
struct device *dev = card->dev;
struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
@@ -1077,8 +1571,18 @@ int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *
for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
*num_devs += adr_link->num_adr;
- for (i = 0; i < adr_link->num_adr; i++)
- *num_ends += adr_link->adr_d[i].num_endpoints;
+ for (i = 0; i < adr_link->num_adr; i++) {
+ const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i];
+ struct asoc_sdw_codec_info *codec_info;
+
+ *num_ends += adr_dev->num_endpoints;
+
+ codec_info = asoc_sdw_find_codec_info_part(adr_dev->adr);
+ if (!codec_info)
+ return -EINVAL;
+
+ *num_aux += codec_info->aux_num;
+ }
}
dev_dbg(dev, "Found %d devices with %d endpoints\n", *num_devs, *num_ends);
@@ -1105,7 +1609,100 @@ struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks
}
EXPORT_SYMBOL_NS(asoc_sdw_find_dailink, "SND_SOC_SDW_UTILS");
+int asoc_sdw_get_dai_type(u32 type)
+{
+ switch (type) {
+ case SDCA_FUNCTION_TYPE_SMART_AMP:
+ case SDCA_FUNCTION_TYPE_SIMPLE_AMP:
+ case SDCA_FUNCTION_TYPE_COMPANION_AMP:
+ return SOC_SDW_DAI_TYPE_AMP;
+ case SDCA_FUNCTION_TYPE_SMART_MIC:
+ case SDCA_FUNCTION_TYPE_SIMPLE_MIC:
+ case SDCA_FUNCTION_TYPE_SPEAKER_MIC:
+ return SOC_SDW_DAI_TYPE_MIC;
+ case SDCA_FUNCTION_TYPE_UAJ:
+ case SDCA_FUNCTION_TYPE_RJ:
+ case SDCA_FUNCTION_TYPE_SIMPLE_JACK:
+ return SOC_SDW_DAI_TYPE_JACK;
+ default:
+ return -EINVAL;
+ }
+}
+EXPORT_SYMBOL_NS(asoc_sdw_get_dai_type, "SND_SOC_SDW_UTILS");
+
+/*
+ * Check if the SDCA endpoint is present by the SDW peripheral
+ *
+ * @dev: Device pointer
+ * @codec_info: Codec info pointer
+ * @adr_link: ACPI link address
+ * @adr_index: Index of the ACPI link address
+ * @end_index: Index of the endpoint
+ *
+ * Return: 1 if the endpoint is present,
+ * 0 if the endpoint is not present,
+ * negative error code.
+ */
+
+static int is_sdca_endpoint_present(struct device *dev,
+ struct asoc_sdw_codec_info *codec_info,
+ const struct snd_soc_acpi_link_adr *adr_link,
+ int adr_index, int end_index)
+{
+ const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[adr_index];
+ const struct snd_soc_acpi_endpoint *adr_end;
+ const struct asoc_sdw_dai_info *dai_info;
+ struct sdw_slave *slave;
+ struct device *sdw_dev;
+ const char *sdw_codec_name;
+ int ret, i;
+
+ adr_end = &adr_dev->endpoints[end_index];
+ dai_info = &codec_info->dais[adr_end->num];
+
+ sdw_codec_name = _asoc_sdw_get_codec_name(dev, adr_link, adr_index);
+ if (!sdw_codec_name)
+ return -ENOMEM;
+
+ sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_codec_name);
+ if (!sdw_dev) {
+ dev_err(dev, "codec %s not found\n", sdw_codec_name);
+ return -EINVAL;
+ }
+
+ slave = dev_to_sdw_dev(sdw_dev);
+
+ /* Make sure BIOS provides SDCA properties */
+ if (!slave->sdca_data.interface_revision) {
+ dev_warn(&slave->dev, "SDCA properties not found in the BIOS\n");
+ ret = 1;
+ goto put_device;
+ }
+
+ for (i = 0; i < slave->sdca_data.num_functions; i++) {
+ int dai_type = asoc_sdw_get_dai_type(slave->sdca_data.function[i].type);
+
+ if (dai_type == dai_info->dai_type) {
+ dev_dbg(&slave->dev, "DAI type %d sdca function %s found\n",
+ dai_type, slave->sdca_data.function[i].name);
+ ret = 1;
+ goto put_device;
+ }
+ }
+
+ dev_dbg(&slave->dev,
+ "SDCA device function for DAI type %d not supported, skip endpoint\n",
+ dai_info->dai_type);
+
+ ret = 0;
+
+put_device:
+ put_device(sdw_dev);
+ return ret;
+}
+
int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
+ struct snd_soc_aux_dev *soc_aux,
struct asoc_sdw_dailink *soc_dais,
struct asoc_sdw_endpoint *soc_ends,
int *num_devs)
@@ -1133,6 +1730,7 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i];
struct asoc_sdw_codec_info *codec_info;
const char *codec_name;
+ bool check_sdca = false;
if (!adr_dev->name_prefix) {
dev_err(dev, "codec 0x%llx does not have a name prefix\n",
@@ -1144,16 +1742,22 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
if (!codec_info)
return -EINVAL;
- ctx->ignore_internal_dmic |= codec_info->ignore_internal_dmic;
-
- codec_name = asoc_sdw_get_codec_name(dev, codec_info, adr_link, i);
- if (!codec_name)
- return -ENOMEM;
-
- dev_dbg(dev, "Adding prefix %s for %s\n",
- adr_dev->name_prefix, codec_name);
+ for (j = 0; j < codec_info->aux_num; j++) {
+ struct snd_soc_component *component;
+
+ component = snd_soc_lookup_component_by_name(codec_info->auxs[j].codec_name);
+ if (component) {
+ dev_dbg(dev, "%s found component %s for aux name %s\n",
+ __func__, component->name,
+ codec_info->auxs[j].codec_name);
+ soc_aux->dlc.name = component->name;
+ } else {
+ soc_aux->dlc.name = codec_info->auxs[j].codec_name;
+ }
+ soc_aux++;
+ }
- soc_end->name_prefix = adr_dev->name_prefix;
+ ctx->ignore_internal_dmic |= codec_info->ignore_internal_dmic;
if (codec_info->count_sidecar && codec_info->add_sidecar) {
ret = codec_info->count_sidecar(card, &num_dais, num_devs);
@@ -1163,6 +1767,9 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
soc_end->include_sidecar = true;
}
+ if (SDW_CLASS_ID(adr_dev->adr) && adr_dev->num_endpoints > 1)
+ check_sdca = true;
+
for (j = 0; j < adr_dev->num_endpoints; j++) {
const struct snd_soc_acpi_endpoint *adr_end;
const struct asoc_sdw_dai_info *dai_info;
@@ -1173,9 +1780,39 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
dai_info = &codec_info->dais[adr_end->num];
soc_dai = asoc_sdw_find_dailink(soc_dais, adr_end);
- if (dai_info->quirk &&
- !(dai_info->quirk_exclude ^ !!(dai_info->quirk & ctx->mc_quirk)))
- continue;
+ /*
+ * quirk should have higher priority than the sdca properties
+ * in the BIOS. We can't always check the DAI quirk because we
+ * will set the mc_quirk when the BIOS doesn't provide the right
+ * information. The endpoint will be skipped if the dai_info->
+ * quirk_exclude and mc_quirk are both not set if we always skip
+ * the endpoint according to the quirk information. We need to
+ * keep the endpoint if it is present in the BIOS. So, only
+ * check the DAI quirk when the mc_quirk is set or SDCA endpoint
+ * present check is not needed.
+ */
+ if (dai_info->quirk & ctx->mc_quirk || !check_sdca) {
+ /*
+ * Check the endpoint if a matching quirk is set or SDCA
+ * endpoint check is not necessary
+ */
+ if (dai_info->quirk &&
+ !(dai_info->quirk_exclude ^ !!(dai_info->quirk & ctx->mc_quirk))) {
+ (*num_devs)--;
+ continue;
+ }
+ } else {
+ /* Check SDCA codec endpoint if there is no matching quirk */
+ ret = is_sdca_endpoint_present(dev, codec_info, adr_link, i, j);
+ if (ret < 0)
+ return ret;
+
+ /* The endpoint is not present, skip */
+ if (!ret) {
+ (*num_devs)--;
+ continue;
+ }
+ }
dev_dbg(dev,
"Add dev: %d, 0x%llx end: %d, dai: %d, %c/%c to %s: %d\n",
@@ -1213,6 +1850,16 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
num_link_dailinks += !!list_empty(&soc_dai->endpoints);
list_add_tail(&soc_end->list, &soc_dai->endpoints);
+ codec_name = asoc_sdw_get_codec_name(dev, dai_info,
+ adr_link, i);
+ if (!codec_name)
+ return -ENOMEM;
+
+ dev_dbg(dev, "Adding prefix %s for %s\n",
+ adr_dev->name_prefix, codec_name);
+
+ soc_end->name_prefix = adr_dev->name_prefix;
+
soc_end->link_mask = adr_link->mask;
soc_end->codec_name = codec_name;
soc_end->codec_info = codec_info;