summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2024-12-03 16:57:11 +0000
committerMark Brown <broonie@kernel.org>2024-12-03 16:57:11 +0000
commit31823f27f84bfa06be20f98ec9be63a671307d63 (patch)
tree3990fba3f9e42cd96c001adab62b6fe441712c6c
parent9d6aacda3ad546048e02d83e5831e0b415382518 (diff)
parent484c997e03cec04da6f69c2c17e854b22aa0f98f (diff)
ASoC: Splitting cs35l56 SoundWire DAI into separate
Merge series from Bard Liao <yung-chuan.liao@linux.intel.com>: This series prepares for dissimilar aggregation of CS42L43 + CS35L56 speaker playback. The CS35L56 SoundWire DAI is split into separate DAIs for playback and capture so they can be routed and aggregated differently. The cs_amp driver is also updated to enable different TX (capture) slots on each CS35L56 on a bus, so that the captures can be aggregated.
-rw-r--r--include/sound/soc_sdw_utils.h2
-rw-r--r--sound/soc/codecs/cs35l56.c8
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c76
-rw-r--r--sound/soc/sdw_utils/soc_sdw_cs_amp.c46
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c13
5 files changed, 133 insertions, 12 deletions
diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h
index 0e82598e10af..36a4a1e1d8ca 100644
--- a/include/sound/soc_sdw_utils.h
+++ b/include/sound/soc_sdw_utils.h
@@ -224,6 +224,8 @@ int asoc_sdw_cs_amp_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
struct asoc_sdw_codec_info *info,
bool playback);
+int asoc_sdw_cs_spk_feedback_rtd_init(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_dai *dai);
/* MAXIM codec support */
int asoc_sdw_maxim_init(struct snd_soc_card *card,
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index 757ade6373ed..5c099443eb7a 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -646,6 +646,12 @@ static struct snd_soc_dai_driver cs35l56_dai[] = {
.rates = CS35L56_RATES,
.formats = CS35L56_RX_FORMATS,
},
+ .symmetric_rate = 1,
+ .ops = &cs35l56_sdw_dai_ops,
+ },
+ {
+ .name = "cs35l56-sdw1c",
+ .id = 2,
.capture = {
.stream_name = "SDW1 Capture",
.channels_min = 1,
@@ -655,7 +661,7 @@ static struct snd_soc_dai_driver cs35l56_dai[] = {
},
.symmetric_rate = 1,
.ops = &cs35l56_sdw_dai_ops,
- }
+ },
};
static int cs35l56_write_cal(struct cs35l56_private *cs35l56)
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 0b37465b6c53..9892efd8e9c2 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -441,6 +441,66 @@ static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = {
}
};
+static const struct snd_soc_acpi_endpoint cs35l56_l_fb_endpoints[] = {
+ { /* Speaker Playback Endpoint */
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 0,
+ .group_id = 1,
+ },
+ { /* Feedback Capture Endpoint */
+ .num = 1,
+ .aggregated = 1,
+ .group_position = 0,
+ .group_id = 2,
+ },
+};
+
+static const struct snd_soc_acpi_endpoint cs35l56_r_fb_endpoints[] = {
+ { /* Speaker Playback Endpoint */
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 1,
+ .group_id = 1,
+ },
+ { /* Feedback Capture Endpoint */
+ .num = 1,
+ .aggregated = 1,
+ .group_position = 1,
+ .group_id = 2,
+ },
+};
+
+static const struct snd_soc_acpi_endpoint cs35l56_2_fb_endpoints[] = {
+ { /* Speaker Playback Endpoint */
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 2,
+ .group_id = 1,
+ },
+ { /* Feedback Capture Endpoint */
+ .num = 1,
+ .aggregated = 1,
+ .group_position = 2,
+ .group_id = 2,
+ },
+};
+
+static const struct snd_soc_acpi_endpoint cs35l56_3_fb_endpoints[] = {
+ { /* Speaker Playback Endpoint */
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 3,
+ .group_id = 1,
+ },
+ { /* Feedback Capture Endpoint */
+ .num = 1,
+ .aggregated = 1,
+ .group_position = 3,
+ .group_id = 2,
+ },
+};
+
static const struct snd_soc_acpi_adr_device cs35l56_1_adr[] = {
{
.adr = 0x00013701FA355601ull,
@@ -474,14 +534,14 @@ static const struct snd_soc_acpi_adr_device cs35l56_2_adr[] = {
static const struct snd_soc_acpi_adr_device cs35l56_2_r_adr[] = {
{
.adr = 0x00023201FA355601ull,
- .num_endpoints = 1,
- .endpoints = &spk_r_endpoint,
+ .num_endpoints = ARRAY_SIZE(cs35l56_r_fb_endpoints),
+ .endpoints = cs35l56_r_fb_endpoints,
.name_prefix = "AMP3"
},
{
.adr = 0x00023301FA355601ull,
- .num_endpoints = 1,
- .endpoints = &spk_3_endpoint,
+ .num_endpoints = ARRAY_SIZE(cs35l56_3_fb_endpoints),
+ .endpoints = cs35l56_3_fb_endpoints,
.name_prefix = "AMP4"
}
@@ -490,14 +550,14 @@ static const struct snd_soc_acpi_adr_device cs35l56_2_r_adr[] = {
static const struct snd_soc_acpi_adr_device cs35l56_3_l_adr[] = {
{
.adr = 0x00033001fa355601ull,
- .num_endpoints = 1,
- .endpoints = &spk_l_endpoint,
+ .num_endpoints = ARRAY_SIZE(cs35l56_l_fb_endpoints),
+ .endpoints = cs35l56_l_fb_endpoints,
.name_prefix = "AMP1"
},
{
.adr = 0x00033101fa355601ull,
- .num_endpoints = 1,
- .endpoints = &spk_2_endpoint,
+ .num_endpoints = ARRAY_SIZE(cs35l56_2_fb_endpoints),
+ .endpoints = cs35l56_2_fb_endpoints,
.name_prefix = "AMP2"
}
};
diff --git a/sound/soc/sdw_utils/soc_sdw_cs_amp.c b/sound/soc/sdw_utils/soc_sdw_cs_amp.c
index 58b059b68016..9146a421e02c 100644
--- a/sound/soc/sdw_utils/soc_sdw_cs_amp.c
+++ b/sound/soc/sdw_utils/soc_sdw_cs_amp.c
@@ -15,6 +15,7 @@
#include <sound/soc_sdw_utils.h>
#define CODEC_NAME_SIZE 8
+#define CS_AMP_CHANNELS_PER_AMP 4
int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
{
@@ -48,6 +49,51 @@ int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai
}
EXPORT_SYMBOL_NS(asoc_sdw_cs_spk_rtd_init, SND_SOC_SDW_UTILS);
+int asoc_sdw_cs_spk_feedback_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
+{
+ const struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ const struct snd_soc_dai_link_ch_map *ch_map;
+ const struct snd_soc_dai_link_component *codec_dlc;
+ struct snd_soc_dai *codec_dai;
+ u8 ch_slot[8] = {};
+ unsigned int amps_per_bus, ch_per_amp, mask;
+ int i, ret;
+
+ WARN_ON(dai_link->num_cpus > ARRAY_SIZE(ch_slot));
+
+ /*
+ * CS35L56 has 4 TX channels. When the capture is aggregated the
+ * same bus slots will be allocated to all the amps on a bus. Only
+ * one amp on that bus can be transmitting in each slot so divide
+ * the available 4 slots between all the amps on a bus.
+ */
+ amps_per_bus = dai_link->num_codecs / dai_link->num_cpus;
+ if ((amps_per_bus == 0) || (amps_per_bus > CS_AMP_CHANNELS_PER_AMP)) {
+ dev_err(rtd->card->dev, "Illegal num_codecs:%u / num_cpus:%u\n",
+ dai_link->num_codecs, dai_link->num_cpus);
+ return -EINVAL;
+ }
+
+ ch_per_amp = CS_AMP_CHANNELS_PER_AMP / amps_per_bus;
+
+ for_each_rtd_ch_maps(rtd, i, ch_map) {
+ codec_dlc = snd_soc_link_to_codec(rtd->dai_link, i);
+ codec_dai = snd_soc_find_dai(codec_dlc);
+ mask = GENMASK(ch_per_amp - 1, 0) << ch_slot[ch_map->cpu];
+
+ ret = snd_soc_dai_set_tdm_slot(codec_dai, 0, mask, 4, 32);
+ if (ret < 0) {
+ dev_err(rtd->card->dev, "Failed to set TDM slot:%d\n", ret);
+ return ret;
+ }
+
+ ch_slot[ch_map->cpu] += ch_per_amp;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_cs_spk_feedback_rtd_init, SND_SOC_SDW_UTILS);
+
int asoc_sdw_cs_amp_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
struct asoc_sdw_codec_info *info,
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 19bd02e2cd6d..375b46c5b429 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -488,10 +488,10 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.part_id = 0x3556,
.dais = {
{
- .direction = {true, true},
+ .direction = {true, false},
.dai_name = "cs35l56-sdw1",
.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,8 +499,15 @@ 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,
},
{
.part_id = 0x4242,